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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Michael Winkler
23  * @author Gerald Gamrath
24  * @author Domenico Salvagnin
25  *
26  * Linear constraints are separated with a high priority, because they are easy
27  * to separate. Instead of using the global cut pool, the same effect can be
28  * implemented by adding linear constraints to the root node, such that they are
29  * separated each time, the linear constraints are separated. A constraint
30  * handler, which generates linear constraints in this way should have a lower
31  * separation priority than the linear constraint handler, and it should have a
32  * separation frequency that is a multiple of the frequency of the linear
33  * constraint handler. In this way, it can be avoided to separate the same cut
34  * twice, because if a separation run of the handler is always preceded by a
35  * separation of the linear constraints, the priorily added constraints are
36  * always satisfied.
37  *
38  * Linear constraints are enforced and checked with a very low priority. Checking
39  * of (many) linear constraints is much more involved than checking the solution
40  * values for integrality. Because we are separating the linear constraints quite
41  * often, it is only necessary to enforce them for integral solutions. A constraint
42  * handler which generates pool cuts in its enforcing method should have an
43  * enforcing priority smaller than that of the linear constraint handler to avoid
44  * regenerating constraints which already exist.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include <assert.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <ctype.h>
53 
54 #include "scip/cons_linear.h"
55 #include "scip/cons_knapsack.h"
56 #include "scip/cons_quadratic.h"
57 #include "scip/cons_nonlinear.h"
58 #include "scip/pub_misc.h"
59 #include "scip/debug.h"
60 
61 #define CONSHDLR_NAME "linear"
62 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
63 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
64 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
65 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
66 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
67 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
68 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
69  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
70 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
71 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
72 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
73 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
74 
75 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
76 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
77 
78 #define EVENTHDLR_NAME "linear"
79 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
80 
81 #define CONFLICTHDLR_NAME "linear"
82 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
83 #define CONFLICTHDLR_PRIORITY -1000000
84 
85 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
86 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
87 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
88 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
89 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
90 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
91 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
92 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
93 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
94  * comparison round */
95 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
96  * propagation? */
97 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
98  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
99 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
100  * (0.0: disable constraint aggregation) */
101 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
102  * (faster, but numerically less stable) */
103 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
104  * to best node's dual bound for separating knapsack cardinality cuts */
105 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
106  * the ones with non-zero dual value? */
107 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
108 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
109 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
110 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
111 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
112  * constraints using the cheapest variable? */
113 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
114  * function defining an upper bound and prevent these constraints from
115  * entering the LP */
116 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
117  * function defining a lower bound and prevent these constraints from
118  * entering the LP */
119 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
120  * objective function */
121 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
122 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
123 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
124 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
125 
126 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
127  * removed afterwards? */
128 
129 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
130 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
131 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
132  * type
133  */
134 
135 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
136 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
139 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
140 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
141 
142 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
143  * maybe in fullDualPresolve(), see convertLongEquality()
144  */
147 /** constraint data for linear constraints */
148 struct SCIP_ConsData
149 {
150  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
151  SCIP_Real rhs; /**< right hand side of row */
152  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
153  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
154  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
155  * activity, ignoring the coefficients contributing with infinite value */
156  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
157  * activity, ignoring the coefficients contributing with infinite value */
158  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
159  * over all contributing values */
160  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
161  * over all contributing values */
162  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
163  * activity, ignoring the coefficients contributing with infinite value */
164  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
165  * activity, ignoring the coefficients contributing with infinite value */
166  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
167  * over all contributing values */
168  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
169  * over all contributing values */
170  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
171  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
172  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
173  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
174  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
175  SCIP_VAR** vars; /**< variables of constraint entries */
176  SCIP_Real* vals; /**< coefficients of constraint entries */
177  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
178  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
179  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
180  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
181  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
182  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
183  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
184  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
185  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
186  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
187  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
188  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
189  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
190  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
191  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
192  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
193  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
194  int varssize; /**< size of the vars- and vals-arrays */
195  int nvars; /**< number of nonzeros in constraint */
196  int nbinvars; /**< the number of binary variables in the constraint, only valid after
197  * sorting in stage >= SCIP_STAGE_INITSOLVE
198  */
199  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
200  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
201  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
202  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
203  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
204  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
205  unsigned int validminact:1; /**< is the local minactivity valid? */
206  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
207  unsigned int validglbminact:1; /**< is the global minactivity valid? */
208  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
209  unsigned int presolved:1; /**< is constraint already presolved? */
210  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
211  unsigned int validsignature:1; /**< is the bit signature valid? */
212  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
213  unsigned int normalized:1; /**< is the constraint in normalized form? */
214  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
215  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
216  unsigned int sorted:1; /**< are the constraint's variables sorted? */
217  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
218  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
219  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
220  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
221  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
222  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
223  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
224  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
225  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
226 };
227 
228 /** event data for bound change event */
229 struct SCIP_EventData
230 {
231  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
232  int varpos; /**< position of variable in vars array */
233  int filterpos; /**< position of event in variable's event filter */
234 };
235 
236 /** constraint handler data */
237 struct SCIP_ConshdlrData
238 {
239  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
240  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
241  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
242  * (0.0: disable constraint aggregation) */
243  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
244  * to best node's dual bound for separating knapsack cardinality cuts */
245  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
246  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
247  * (faster, but numerically less stable) */
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  int naddconss; /**< number of added constraints */
257  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
258  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
259  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
260  * the ones with non-zero dual value? */
261  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
262  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
263  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
264  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
265  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
266  * constraints using the cheapest variable? */
267  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
268  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
269  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
270  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
271  * function defining an upper bound and prevent these constraints from
272  * entering the LP */
273  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
274  * function defining a lower bound and prevent these constraints from
275  * entering the LP */
276  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
277  * the objective function */
278  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
279  * infeasibility, and extract sub-constraints from ranged rows and
280  * equations */
281  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
282  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
283  int rangedrowfreq; /**< frequency for applying ranged row propagation */
284  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
285  * removed afterwards? */
286 };
287 
288 /** linear constraint update method */
289 struct SCIP_LinConsUpgrade
290 {
291  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
292  int priority; /**< priority of upgrading method */
293  SCIP_Bool active; /**< is upgrading enabled */
294 };
295 
296 
297 /*
298  * Propagation rules
299  */
300 
301 enum Proprule
302 {
303  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
304  * variable due to the right hand side of the inequality */
305  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
306  * variable due to the left hand side of the inequality */
307  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
308  * single variable in this reanged row */
309  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
310 };
311 typedef enum Proprule PROPRULE;
312 
313 /** inference information */
314 struct InferInfo
315 {
316  union
317  {
318  struct
319  {
320  unsigned int proprule:8; /**< propagation rule that was applied */
321  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
322  } asbits;
323  int asint; /**< inference information as a single int value */
324  } val;
325 };
326 typedef struct InferInfo INFERINFO;
327 
328 /** converts an integer into an inference information */
329 static
331  int i /**< integer to convert */
332  )
333 {
334  INFERINFO inferinfo;
335 
336  inferinfo.val.asint = i;
337 
338  return inferinfo;
339 }
340 
341 /** converts an inference information into an int */
342 static
344  INFERINFO inferinfo /**< inference information to convert */
345  )
346 {
347  return inferinfo.val.asint;
348 }
349 
350 /** returns the propagation rule stored in the inference information */
351 static
353  INFERINFO inferinfo /**< inference information to convert */
354  )
355 {
356  return (int) inferinfo.val.asbits.proprule;
357 }
358 
359 /** returns the position stored in the inference information */
360 static
361 int inferInfoGetPos(
362  INFERINFO inferinfo /**< inference information to convert */
363  )
364 {
365  return (int) inferinfo.val.asbits.pos;
366 }
367 
368 /** constructs an inference information out of a propagation rule and a position number */
369 static
371  PROPRULE proprule, /**< propagation rule that deduced the value */
372  int pos /**< variable position, the propagation rule was applied at */
373  )
374 {
375  INFERINFO inferinfo;
376 
377  assert(pos >= 0);
378  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
379  assert(pos < (1<<24));
380 
381  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
382  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
383 
384  return inferinfo;
385 }
386 
387 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
388 static
389 int getInferInt(
390  PROPRULE proprule, /**< propagation rule that deduced the value */
391  int pos /**< variable position, the propagation rule was applied at */
392  )
393 {
394  return inferInfoToInt(getInferInfo(proprule, pos));
395 }
396 
397 
398 /*
399  * memory growing methods for dynamically allocated arrays
400  */
401 
402 /** ensures, that linconsupgrades array can store at least num entries */
403 static
405  SCIP* scip, /**< SCIP data structure */
406  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
407  int num /**< minimum number of entries to store */
408  )
409 {
410  assert(scip != NULL);
411  assert(conshdlrdata != NULL);
412  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
413 
414  if( num > conshdlrdata->linconsupgradessize )
415  {
416  int newsize;
417 
418  newsize = SCIPcalcMemGrowSize(scip, num);
419  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
420  conshdlrdata->linconsupgradessize = newsize;
421  }
422  assert(num <= conshdlrdata->linconsupgradessize);
423 
424  return SCIP_OKAY;
425 }
426 
427 /** ensures, that vars and vals arrays can store at least num entries */
428 static
430  SCIP* scip, /**< SCIP data structure */
431  SCIP_CONSDATA* consdata, /**< linear constraint data */
432  int num /**< minimum number of entries to store */
433  )
434 {
435  assert(scip != NULL);
436  assert(consdata != NULL);
437  assert(consdata->nvars <= consdata->varssize);
438 
439  if( num > consdata->varssize )
440  {
441  int newsize;
442 
443  newsize = SCIPcalcMemGrowSize(scip, num);
444  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
445  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
446  if( consdata->eventdata != NULL )
447  {
448  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
449  }
450  consdata->varssize = newsize;
451  }
452  assert(num <= consdata->varssize);
453 
454  return SCIP_OKAY;
455 }
456 
457 
458 /*
459  * local methods for managing linear constraint update methods
460  */
461 
462 /** creates a linear constraint upgrade data object */
463 static
465  SCIP* scip, /**< SCIP data structure */
466  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
467  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
468  int priority /**< priority of upgrading method */
469  )
470 {
471  assert(scip != NULL);
472  assert(linconsupgrade != NULL);
473  assert(linconsupgd != NULL);
474 
475  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
476  (*linconsupgrade)->linconsupgd = linconsupgd;
477  (*linconsupgrade)->priority = priority;
478  (*linconsupgrade)->active = TRUE;
479 
480  return SCIP_OKAY;
481 }
482 
483 /** frees a linear constraint upgrade data object */
484 static
485 void linconsupgradeFree(
486  SCIP* scip, /**< SCIP data structure */
487  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
488  )
489 {
490  assert(scip != NULL);
491  assert(linconsupgrade != NULL);
492  assert(*linconsupgrade != NULL);
493 
494  SCIPfreeBlockMemory(scip, linconsupgrade);
495 }
496 
497 /** creates constraint handler data for linear constraint handler */
498 static
500  SCIP* scip, /**< SCIP data structure */
501  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
502  SCIP_EVENTHDLR* eventhdlr /**< event handler */
503  )
504 {
505  assert(scip != NULL);
506  assert(conshdlrdata != NULL);
507  assert(eventhdlr != NULL);
508 
509  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
510  (*conshdlrdata)->linconsupgrades = NULL;
511  (*conshdlrdata)->linconsupgradessize = 0;
512  (*conshdlrdata)->nlinconsupgrades = 0;
513  (*conshdlrdata)->naddconss = 0;
514 
515  /* set event handler for updating linear constraint activity bounds */
516  (*conshdlrdata)->eventhdlr = eventhdlr;
517 
518  return SCIP_OKAY;
519 }
520 
521 /** frees constraint handler data for linear constraint handler */
522 static
523 void conshdlrdataFree(
524  SCIP* scip, /**< SCIP data structure */
525  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
526  )
527 {
528  int i;
529 
530  assert(scip != NULL);
531  assert(conshdlrdata != NULL);
532  assert(*conshdlrdata != NULL);
533 
534  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
535  {
536  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
537  }
538  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
539 
540  SCIPfreeBlockMemory(scip, conshdlrdata);
541 }
542 
543 /** creates a linear constraint upgrade data object */
544 static
546  SCIP* scip, /**< SCIP data structure */
547  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
548  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
549  const char* conshdlrname /**< name of the constraint handler */
550  )
551 {
552  int i;
553 
554  assert(scip != NULL);
555  assert(conshdlrdata != NULL);
556  assert(linconsupgd != NULL);
557  assert(conshdlrname != NULL);
558 
559  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
560  {
561  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
562  {
563 #ifdef SCIP_DEBUG
564  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
565 #endif
566  return TRUE;
567  }
568  }
569 
570  return FALSE;
571 }
572 
573 /** adds a linear constraint update method to the constraint handler's data */
574 static
576  SCIP* scip, /**< SCIP data structure */
577  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
578  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
579  )
580 {
581  int i;
582 
583  assert(scip != NULL);
584  assert(conshdlrdata != NULL);
585  assert(linconsupgrade != NULL);
586 
587  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
588 
589  for( i = conshdlrdata->nlinconsupgrades;
590  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
591  {
592  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
593  }
594  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
595  conshdlrdata->linconsupgrades[i] = linconsupgrade;
596  conshdlrdata->nlinconsupgrades++;
597 
598  return SCIP_OKAY;
599 }
600 
601 /*
602  * local methods
603  */
604 
605 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
606 static
608  SCIP* scip, /**< SCIP data structure */
609  SCIP_CONS* cons, /**< linear constraint */
610  SCIP_VAR* var, /**< variable of constraint entry */
611  SCIP_Real val /**< coefficient of constraint entry */
612  )
613 {
614  SCIP_CONSDATA* consdata;
615 
616  assert(scip != NULL);
617  assert(cons != NULL);
618  assert(var != NULL);
619 
620  consdata = SCIPconsGetData(cons);
621  assert(consdata != NULL);
622  assert(!SCIPisZero(scip, val));
623 
624  if( SCIPisPositive(scip, val) )
625  {
626  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
627  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
628  }
629  else
630  {
631  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
632  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
633  }
634 
635  return SCIP_OKAY;
636 }
637 
638 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
639 static
641  SCIP* scip, /**< SCIP data structure */
642  SCIP_CONS* cons, /**< linear constraint */
643  SCIP_VAR* var, /**< variable of constraint entry */
644  SCIP_Real val /**< coefficient of constraint entry */
645  )
646 {
647  SCIP_CONSDATA* consdata;
648 
649  assert(scip != NULL);
650  assert(cons != NULL);
651  assert(var != NULL);
652 
653  consdata = SCIPconsGetData(cons);
654  assert(consdata != NULL);
655  assert(!SCIPisZero(scip, val));
656 
657  if( SCIPisPositive(scip, val) )
658  {
659  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
660  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
661  }
662  else
663  {
664  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
665  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
666  }
667 
668  return SCIP_OKAY;
669 }
670 
671 /** creates event data for variable at given position, and catches events */
672 /**! [SnippetDebugAssertions] */
673 static
675  SCIP* scip, /**< SCIP data structure */
676  SCIP_CONS* cons, /**< linear constraint */
677  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
678  int pos /**< array position of variable to catch bound change events for */
679  )
680 {
681  SCIP_CONSDATA* consdata;
682  assert(scip != NULL);
683  assert(cons != NULL);
684  assert(eventhdlr != NULL);
685 
686  consdata = SCIPconsGetData(cons);
687  assert(consdata != NULL);
688 
689  assert(0 <= pos && pos < consdata->nvars);
690  assert(consdata->vars != NULL);
691  assert(consdata->vars[pos] != NULL);
692  assert(SCIPvarIsTransformed(consdata->vars[pos]));
693  assert(consdata->eventdata != NULL);
694  assert(consdata->eventdata[pos] == NULL);
695 
696  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
697  consdata->eventdata[pos]->cons = cons;
698  consdata->eventdata[pos]->varpos = pos;
699 
700  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
703  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
704 
705  return SCIP_OKAY;
706 }
707 /**! [SnippetDebugAssertions] */
708 
709 /** deletes event data for variable at given position, and drops events */
710 static
712  SCIP* scip, /**< SCIP data structure */
713  SCIP_CONS* cons, /**< linear constraint */
714  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
715  int pos /**< array position of variable to catch bound change events for */
716  )
717 {
718  SCIP_CONSDATA* consdata;
719  assert(scip != NULL);
720  assert(cons != NULL);
721  assert(eventhdlr != NULL);
722 
723  consdata = SCIPconsGetData(cons);
724  assert(consdata != NULL);
725 
726  assert(0 <= pos && pos < consdata->nvars);
727  assert(consdata->vars[pos] != NULL);
728  assert(consdata->eventdata != NULL);
729  assert(consdata->eventdata[pos] != NULL);
730  assert(consdata->eventdata[pos]->cons == cons);
731  assert(consdata->eventdata[pos]->varpos == pos);
732 
733  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
736  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
737 
738  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
739 
740  return SCIP_OKAY;
741 }
742 
743 /** catches bound change events for all variables in transformed linear constraint */
744 static
746  SCIP* scip, /**< SCIP data structure */
747  SCIP_CONS* cons, /**< linear constraint */
748  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
749  )
750 {
751  SCIP_CONSDATA* consdata;
752  int i;
753 
754  assert(scip != NULL);
755  assert(cons != NULL);
756 
757  consdata = SCIPconsGetData(cons);
758  assert(consdata != NULL);
759  assert(consdata->eventdata == NULL);
760 
761  /* allocate eventdata array */
762  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
763  assert(consdata->eventdata != NULL);
764  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
765 
766  /* catch event for every single variable */
767  for( i = 0; i < consdata->nvars; ++i )
768  {
769  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
770  }
771 
772  return SCIP_OKAY;
773 }
774 
775 /** drops bound change events for all variables in transformed linear constraint */
776 static
778  SCIP* scip, /**< SCIP data structure */
779  SCIP_CONS* cons, /**< linear constraint */
780  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
781  )
782 {
783  SCIP_CONSDATA* consdata;
784  int i;
785 
786  assert(scip != NULL);
787  assert(cons != NULL);
788 
789  consdata = SCIPconsGetData(cons);
790  assert(consdata != NULL);
791  assert(consdata->eventdata != NULL);
792 
793  /* drop event of every single variable */
794  for( i = consdata->nvars - 1; i >= 0; --i )
795  {
796  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
797  }
798 
799  /* free eventdata array */
800  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
801  assert(consdata->eventdata == NULL);
802 
803  return SCIP_OKAY;
804 }
805 
806 /** creates a linear constraint data */
807 static
809  SCIP* scip, /**< SCIP data structure */
810  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
811  int nvars, /**< number of nonzeros in the constraint */
812  SCIP_VAR** vars, /**< array with variables of constraint entries */
813  SCIP_Real* vals, /**< array with coefficients of constraint entries */
814  SCIP_Real lhs, /**< left hand side of row */
815  SCIP_Real rhs /**< right hand side of row */
816  )
817 {
818  int v;
819  SCIP_Real constant;
820 
821  assert(scip != NULL);
822  assert(consdata != NULL);
823  assert(nvars == 0 || vars != NULL);
824  assert(nvars == 0 || vals != NULL);
826  if( SCIPisInfinity(scip, rhs) )
827  rhs = SCIPinfinity(scip);
828  else if( SCIPisInfinity(scip, -rhs) )
829  rhs = -SCIPinfinity(scip);
830 
831  if( SCIPisInfinity(scip, -lhs) )
832  lhs = -SCIPinfinity(scip);
833  else if( SCIPisInfinity(scip, lhs) )
834  lhs = SCIPinfinity(scip);
835 
836  if( SCIPisGT(scip, lhs, rhs) )
837  {
838  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
839  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
840  }
841 
842  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
843 
844  (*consdata)->varssize = 0;
845  (*consdata)->nvars = nvars;
846  (*consdata)->hascontvar = FALSE;
847  (*consdata)->hasnonbinvar = FALSE;
848  (*consdata)->hasnonbinvalid = TRUE;
849  (*consdata)->vars = NULL;
850  (*consdata)->vals = NULL;
851 
852  constant = 0.0;
853  if( nvars > 0 )
854  {
855  int k;
856 
857  SCIP_VAR** varsbuffer;
858  SCIP_Real* valsbuffer;
859 
860  /* copy variables into temporary buffer */
861  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
862  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
863  k = 0;
864 
865  /* loop over variables and sort out fixed ones */
866  for( v = 0; v < nvars; ++v )
867  {
868  SCIP_VAR* var;
869  SCIP_Real val;
870 
871  var = vars[v];
872  val = vals[v];
873 
874  assert(var != NULL);
875  if( !SCIPisZero(scip, val) )
876  {
877  /* treat fixed variable as a constant if problem compression is enabled */
879  {
880  constant += SCIPvarGetLbGlobal(var) * val;
881  }
882  else
883  {
884  varsbuffer[k] = var;
885  valsbuffer[k] = val;
886  k++;
887 
888  /* update hascontvar and hasnonbinvar flags */
889  if( !(*consdata)->hascontvar )
890  {
891  SCIP_VARTYPE vartype = SCIPvarGetType(var);
892 
893  if( vartype != SCIP_VARTYPE_BINARY )
894  {
895  (*consdata)->hasnonbinvar = TRUE;
896 
897  if( vartype == SCIP_VARTYPE_CONTINUOUS )
898  (*consdata)->hascontvar = TRUE;
899  }
900  }
901  }
902  }
903  }
904  (*consdata)->nvars = k;
905 
906  if( k > 0 )
907  {
908  /* copy the possibly reduced buffer arrays into block */
909  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
910  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
911  (*consdata)->varssize = k;
912  }
913  /* free temporary buffer */
914  SCIPfreeBufferArray(scip, &valsbuffer);
915  SCIPfreeBufferArray(scip, &varsbuffer);
916  }
917 
918  (*consdata)->eventdata = NULL;
919 
920  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
921  if( !SCIPisZero(scip, constant) )
922  {
923  if( !SCIPisInfinity(scip, REALABS(lhs)) )
924  lhs -= constant;
925 
926  if( !SCIPisInfinity(scip, REALABS(rhs)) )
927  rhs -= constant;
928  }
929 
930  (*consdata)->row = NULL;
931  (*consdata)->lhs = lhs;
932  (*consdata)->rhs = rhs;
933  (*consdata)->maxabsval = SCIP_INVALID;
934  (*consdata)->minabsval = SCIP_INVALID;
935  (*consdata)->minactivity = SCIP_INVALID;
936  (*consdata)->maxactivity = SCIP_INVALID;
937  (*consdata)->lastminactivity = SCIP_INVALID;
938  (*consdata)->lastmaxactivity = SCIP_INVALID;
939  (*consdata)->maxactdelta = SCIP_INVALID;
940  (*consdata)->maxactdeltavar = NULL;
941  (*consdata)->minactivityneginf = -1;
942  (*consdata)->minactivityposinf = -1;
943  (*consdata)->maxactivityneginf = -1;
944  (*consdata)->maxactivityposinf = -1;
945  (*consdata)->minactivityneghuge = -1;
946  (*consdata)->minactivityposhuge = -1;
947  (*consdata)->maxactivityneghuge = -1;
948  (*consdata)->maxactivityposhuge = -1;
949  (*consdata)->glbminactivity = SCIP_INVALID;
950  (*consdata)->glbmaxactivity = SCIP_INVALID;
951  (*consdata)->lastglbminactivity = SCIP_INVALID;
952  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
953  (*consdata)->glbminactivityneginf = -1;
954  (*consdata)->glbminactivityposinf = -1;
955  (*consdata)->glbmaxactivityneginf = -1;
956  (*consdata)->glbmaxactivityposinf = -1;
957  (*consdata)->glbminactivityneghuge = -1;
958  (*consdata)->glbminactivityposhuge = -1;
959  (*consdata)->glbmaxactivityneghuge = -1;
960  (*consdata)->glbmaxactivityposhuge = -1;
961  (*consdata)->possignature = 0;
962  (*consdata)->negsignature = 0;
963  (*consdata)->validmaxabsval = FALSE;
964  (*consdata)->validminabsval = FALSE;
965  (*consdata)->validactivities = FALSE;
966  (*consdata)->validminact = FALSE;
967  (*consdata)->validmaxact = FALSE;
968  (*consdata)->validglbminact = FALSE;
969  (*consdata)->validglbmaxact = FALSE;
970  (*consdata)->boundstightened = 0;
971  (*consdata)->presolved = FALSE;
972  (*consdata)->removedfixings = FALSE;
973  (*consdata)->validsignature = FALSE;
974  (*consdata)->changed = TRUE;
975  (*consdata)->normalized = FALSE;
976  (*consdata)->upgradetried = FALSE;
977  (*consdata)->upgraded = FALSE;
978  (*consdata)->sorted = (nvars <= 1);
979  (*consdata)->merged = (nvars <= 1);
980  (*consdata)->cliquesadded = FALSE;
981  (*consdata)->implsadded = FALSE;
982  (*consdata)->binvarssorted = FALSE;
983  (*consdata)->nbinvars = -1;
984  (*consdata)->varsdeleted = FALSE;
985  (*consdata)->rangedrowpropagated = 0;
986  (*consdata)->checkabsolute = FALSE;
987 
988  if( SCIPisTransformed(scip) )
989  {
990  /* get transformed variables */
991  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
992  }
993 
994  /* capture variables */
995  for( v = 0; v < (*consdata)->nvars; v++ )
996  {
997  assert((*consdata)->vars[v] != NULL);
998  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
999  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1000  }
1001 
1002  return SCIP_OKAY;
1003 }
1004 
1005 /** frees a linear constraint data */
1006 static
1008  SCIP* scip, /**< SCIP data structure */
1009  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1010  )
1011 {
1012  int v;
1013 
1014  assert(scip != NULL);
1015  assert(consdata != NULL);
1016  assert(*consdata != NULL);
1017  assert((*consdata)->varssize >= 0);
1018 
1019  /* release the row */
1020  if( (*consdata)->row != NULL )
1021  {
1022  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1023  }
1025  /* release variables */
1026  for( v = 0; v < (*consdata)->nvars; v++ )
1027  {
1028  assert((*consdata)->vars[v] != NULL);
1029  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1030  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1031  }
1032 
1033  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1034  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1035  SCIPfreeBlockMemory(scip, consdata);
1036 
1037  return SCIP_OKAY;
1038 }
1039 
1040 /** prints linear constraint in CIP format to file stream */
1041 static
1043  SCIP* scip, /**< SCIP data structure */
1044  SCIP_CONSDATA* consdata, /**< linear constraint data */
1045  FILE* file /**< output file (or NULL for standard output) */
1046  )
1047 {
1048  assert(scip != NULL);
1049  assert(consdata != NULL);
1050 
1051  /* print left hand side for ranged rows */
1052  if( !SCIPisInfinity(scip, -consdata->lhs)
1053  && !SCIPisInfinity(scip, consdata->rhs)
1054  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1055  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1056 
1057  /* print coefficients and variables */
1058  if( consdata->nvars == 0 )
1059  SCIPinfoMessage(scip, file, "0");
1060  else
1061  {
1062  /* post linear sum of the linear constraint */
1063  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1064  }
1065 
1066  /* print right hand side */
1067  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1068  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1069  else if( !SCIPisInfinity(scip, consdata->rhs) )
1070  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1071  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1072  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1073  else
1074  SCIPinfoMessage(scip, file, " [free]");
1075 
1076  return SCIP_OKAY;
1077 }
1078 
1079 /** prints linear constraint and contained solution values of variables to file stream */
1080 static
1082  SCIP* scip, /**< SCIP data structure */
1083  SCIP_CONS* cons, /**< linear constraint */
1084  SCIP_SOL* sol, /**< solution to print */
1085  FILE* file /**< output file (or NULL for standard output) */
1086  )
1087 {
1088  SCIP_CONSDATA* consdata;
1089 
1090  assert(scip != NULL);
1091  assert(cons != NULL);
1092 
1093  consdata = SCIPconsGetData(cons);
1094  assert(consdata != NULL);
1095 
1097 
1098  /* print left hand side for ranged rows */
1099  if( !SCIPisInfinity(scip, -consdata->lhs)
1100  && !SCIPisInfinity(scip, consdata->rhs)
1101  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1102  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1103 
1104  /* print coefficients and variables */
1105  if( consdata->nvars == 0 )
1106  SCIPinfoMessage(scip, file, "0");
1107  else
1108  {
1109  int v;
1110 
1111  /* post linear sum of the linear constraint */
1112  for( v = 0; v < consdata->nvars; ++v )
1113  {
1114  if( consdata->vals != NULL )
1115  {
1116  if( consdata->vals[v] == 1.0 )
1117  {
1118  if( v > 0 )
1119  SCIPinfoMessage(scip, file, " +");
1120  }
1121  else if( consdata->vals[v] == -1.0 )
1122  SCIPinfoMessage(scip, file, " -");
1123  else
1124  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1125  }
1126  else if( consdata->nvars > 0 )
1127  SCIPinfoMessage(scip, file, " +");
1128 
1129  /* print variable name */
1130  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1131 
1132  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1133  }
1134  }
1135 
1136  /* print right hand side */
1137  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1138  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1139  else if( !SCIPisInfinity(scip, consdata->rhs) )
1140  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1141  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1142  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1143  else
1144  SCIPinfoMessage(scip, file, " [free]");
1145 
1146  SCIPinfoMessage(scip, file, ";\n");
1147 
1148  return SCIP_OKAY;
1149 }
1150 
1151 /** invalidates activity bounds, such that they are recalculated in next get */
1152 static
1154  SCIP_CONSDATA* consdata /**< linear constraint */
1155  )
1156 {
1157  assert(consdata != NULL);
1158 
1159  consdata->validactivities = FALSE;
1160  consdata->validminact = FALSE;
1161  consdata->validmaxact = FALSE;
1162  consdata->validglbminact = FALSE;
1163  consdata->validglbmaxact = FALSE;
1164  consdata->validmaxabsval = FALSE;
1165  consdata->validminabsval = FALSE;
1166  consdata->hasnonbinvalid = FALSE;
1167  consdata->minactivity = SCIP_INVALID;
1168  consdata->maxactivity = SCIP_INVALID;
1169  consdata->lastminactivity = SCIP_INVALID;
1170  consdata->lastmaxactivity = SCIP_INVALID;
1171  consdata->maxabsval = SCIP_INVALID;
1172  consdata->minabsval = SCIP_INVALID;
1173  consdata->maxactdelta = SCIP_INVALID;
1174  consdata->maxactdeltavar = NULL;
1175  consdata->minactivityneginf = -1;
1176  consdata->minactivityposinf = -1;
1177  consdata->maxactivityneginf = -1;
1178  consdata->maxactivityposinf = -1;
1179  consdata->minactivityneghuge = -1;
1180  consdata->minactivityposhuge = -1;
1181  consdata->maxactivityneghuge = -1;
1182  consdata->maxactivityposhuge = -1;
1183  consdata->glbminactivity = SCIP_INVALID;
1184  consdata->glbmaxactivity = SCIP_INVALID;
1185  consdata->lastglbminactivity = SCIP_INVALID;
1186  consdata->lastglbmaxactivity = SCIP_INVALID;
1187  consdata->glbminactivityneginf = -1;
1188  consdata->glbminactivityposinf = -1;
1189  consdata->glbmaxactivityneginf = -1;
1190  consdata->glbmaxactivityposinf = -1;
1191  consdata->glbminactivityneghuge = -1;
1192  consdata->glbminactivityposhuge = -1;
1193  consdata->glbmaxactivityneghuge = -1;
1194  consdata->glbmaxactivityposhuge = -1;
1195 }
1196 
1197 /** compute the pseudo activity of a constraint */
1198 static
1200  SCIP* scip, /**< SCIP data structure */
1201  SCIP_CONSDATA* consdata /**< linear constraint data */
1202  )
1203 {
1204  int i;
1205  int pseudoactivityposinf;
1206  int pseudoactivityneginf;
1207  SCIP_Real pseudoactivity;
1208  SCIP_Real bound;
1209  SCIP_Real val;
1210 
1211  pseudoactivity = 0;
1212  pseudoactivityposinf = 0;
1213  pseudoactivityneginf = 0;
1214 
1215  for( i = consdata->nvars - 1; i >= 0; --i )
1216  {
1217  val = consdata->vals[i];
1218  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1219  if( SCIPisInfinity(scip, bound) )
1220  {
1221  if( val > 0.0 )
1222  pseudoactivityposinf++;
1223  else
1224  pseudoactivityneginf++;
1225  }
1226  else
1227  {
1228  if( SCIPisInfinity(scip, -bound) )
1229  {
1230  if( val > 0.0 )
1231  pseudoactivityneginf++;
1232  else
1233  pseudoactivityposinf++;
1234  }
1235  else
1236  pseudoactivity += val * bound;
1237  }
1238  }
1239 
1240  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1241  return SCIP_INVALID;
1242  else if( pseudoactivityneginf > 0 )
1243  return -SCIPinfinity(scip);
1244  else if( pseudoactivityposinf > 0 )
1245  return SCIPinfinity(scip);
1246 
1247  return pseudoactivity;
1248 }
1249 
1250 /** recompute the minactivity of a constraint */
1251 static
1253  SCIP* scip, /**< SCIP data structure */
1254  SCIP_CONSDATA* consdata /**< linear constraint data */
1255  )
1256 {
1257  int i;
1258  SCIP_Real bound;
1259 
1260  consdata->minactivity = 0;
1261 
1262  for( i = consdata->nvars - 1; i >= 0; --i )
1263  {
1264  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1265  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1266  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1267  consdata->minactivity += consdata->vals[i] * bound;
1268  }
1270  /* the activity was just computed from scratch and is valid now */
1271  consdata->validminact = TRUE;
1272 
1273  /* the activity was just computed from scratch, mark it to be reliable */
1274  consdata->lastminactivity = consdata->minactivity;
1275 }
1276 
1277 /** recompute the maxactivity of a constraint */
1278 static
1280  SCIP* scip, /**< SCIP data structure */
1281  SCIP_CONSDATA* consdata /**< linear constraint data */
1282  )
1283 {
1284  int i;
1285  SCIP_Real bound;
1286 
1287  consdata->maxactivity = 0;
1288 
1289  for( i = consdata->nvars - 1; i >= 0; --i )
1290  {
1291  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1292  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1293  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1294  consdata->maxactivity += consdata->vals[i] * bound;
1295  }
1297  /* the activity was just computed from scratch and is valid now */
1298  consdata->validmaxact = TRUE;
1299 
1300  /* the activity was just computed from scratch, mark it to be reliable */
1301  consdata->lastmaxactivity = consdata->maxactivity;
1302 }
1303 
1304 /** recompute the global minactivity of a constraint */
1305 static
1307  SCIP* scip, /**< SCIP data structure */
1308  SCIP_CONSDATA* consdata /**< linear constraint data */
1309  )
1310 {
1311  int i;
1312  SCIP_Real bound;
1313 
1314  consdata->glbminactivity = 0;
1315 
1316  for( i = consdata->nvars - 1; i >= 0; --i )
1317  {
1318  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1319  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1320  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1321  consdata->glbminactivity += consdata->vals[i] * bound;
1322  }
1324  /* the activity was just computed from scratch and is valid now */
1325  consdata->validglbminact = TRUE;
1326 
1327  /* the activity was just computed from scratch, mark it to be reliable */
1328  consdata->lastglbminactivity = consdata->glbminactivity;
1329 }
1330 
1331 /** recompute the global maxactivity of a constraint */
1332 static
1334  SCIP* scip, /**< SCIP data structure */
1335  SCIP_CONSDATA* consdata /**< linear constraint data */
1336  )
1337 {
1338  int i;
1339  SCIP_Real bound;
1340 
1341  consdata->glbmaxactivity = 0;
1342 
1343  for( i = consdata->nvars - 1; i >= 0; --i )
1344  {
1345  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1346  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1347  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1348  consdata->glbmaxactivity += consdata->vals[i] * bound;
1349  }
1351  /* the activity was just computed from scratch and is valid now */
1352  consdata->validglbmaxact = TRUE;
1353 
1354  /* the activity was just computed from scratch, mark it to be reliable */
1355  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1356 }
1357 
1358 /** calculates maximum absolute value of coefficients */
1359 static
1361  SCIP_CONSDATA* consdata /**< linear constraint data */
1362  )
1363 {
1364  SCIP_Real absval;
1365  int i;
1366 
1367  assert(consdata != NULL);
1368  assert(!consdata->validmaxabsval);
1369  assert(consdata->maxabsval >= SCIP_INVALID);
1370 
1371  consdata->validmaxabsval = TRUE;
1372  consdata->maxabsval = 0.0;
1373  for( i = 0; i < consdata->nvars; ++i )
1374  {
1375  absval = consdata->vals[i];
1376  absval = REALABS(absval);
1377  if( absval > consdata->maxabsval )
1378  consdata->maxabsval = absval;
1379  }
1380 }
1381 
1382 /** calculates minimum absolute value of coefficients */
1383 static
1385  SCIP_CONSDATA* consdata /**< linear constraint data */
1386  )
1387 {
1388  SCIP_Real absval;
1389  int i;
1390 
1391  assert(consdata != NULL);
1392  assert(!consdata->validminabsval);
1393  assert(consdata->minabsval >= SCIP_INVALID);
1394 
1395  consdata->validminabsval = TRUE;
1396 
1397  if( consdata->nvars > 0 )
1398  consdata->minabsval = REALABS(consdata->vals[0]);
1399  else
1400  consdata->minabsval = 0.0;
1402  for( i = 1; i < consdata->nvars; ++i )
1403  {
1404  absval = consdata->vals[i];
1405  absval = REALABS(absval);
1406  if( absval < consdata->minabsval )
1407  consdata->minabsval = absval;
1408  }
1409 }
1410 
1411 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1412 static
1414  SCIP_CONSDATA* consdata /**< linear constraint data */
1415  )
1416 {
1417  int v;
1418 
1419  assert(!consdata->hasnonbinvalid);
1420  consdata->hasnonbinvar = FALSE;
1421  consdata->hascontvar = FALSE;
1422 
1423  for( v = consdata->nvars - 1; v >= 0; --v )
1424  {
1425  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1426 
1427  if( vartype != SCIP_VARTYPE_BINARY )
1428  {
1429  consdata->hasnonbinvar = TRUE;
1431  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1432  {
1433  consdata->hascontvar = TRUE;
1434  break;
1435  }
1436  }
1437  }
1438  assert(consdata->hascontvar || v < 0);
1439 
1440  consdata->hasnonbinvalid = TRUE;
1441 }
1442 
1443 
1444 #ifdef CHECKMAXACTDELTA
1445 /* checks that the stored maximal activity delta (if not invalid) is correct */
1446 static
1448  SCIP* scip, /**< SCIP data structure */
1449  SCIP_CONSDATA* consdata /**< linear constraint data */
1450  )
1451 {
1452  if( consdata->maxactdelta != SCIP_INVALID )
1453  {
1454  SCIP_Real maxactdelta = 0.0;
1455  SCIP_Real domain;
1456  SCIP_Real delta;
1457  SCIP_Real lb;
1458  SCIP_Real ub;
1459  int v;
1460 
1461  for( v = consdata->nvars - 1; v >= 0; --v )
1462  {
1463  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1464  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1465 
1466  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1467  {
1468  maxactdelta = SCIPinfinity(scip);
1469  break;
1470  }
1471 
1472  domain = ub - lb;
1473  delta = REALABS(consdata->vals[v]) * domain;
1474 
1475  if( delta > maxactdelta )
1476  {
1477  maxactdelta = delta;
1478  }
1479  }
1480  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1481  }
1482 }
1483 #else
1484 #define checkMaxActivityDelta(scip, consdata) /**/
1485 #endif
1486 
1487 /** recompute maximal activity contribution for a single variable */
1488 static
1490  SCIP* scip, /**< SCIP data structure */
1491  SCIP_CONSDATA* consdata /**< linear constraint data */
1492  )
1493 {
1494  SCIP_Real delta;
1495  int v;
1496 
1497  consdata->maxactdelta = 0.0;
1498 
1499  if( !consdata->hasnonbinvalid )
1500  consdataCheckNonbinvar(consdata);
1502  /* easy case, the problem consists only of binary variables */
1503  if( !consdata->hasnonbinvar )
1504  {
1505  for( v = consdata->nvars - 1; v >= 0; --v )
1506  {
1507  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1508  {
1509  delta = REALABS(consdata->vals[v]);
1510 
1511  if( delta > consdata->maxactdelta )
1512  {
1513  consdata->maxactdelta = delta;
1514  consdata->maxactdeltavar = consdata->vars[v];
1515  }
1516  }
1517  }
1518  return;
1519  }
1520 
1521  for( v = consdata->nvars - 1; v >= 0; --v )
1522  {
1523  SCIP_Real domain;
1524  SCIP_Real lb;
1525  SCIP_Real ub;
1526 
1527  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1528  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1529 
1530  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1531  {
1532  consdata->maxactdelta = SCIPinfinity(scip);
1533  consdata->maxactdeltavar = consdata->vars[v];
1534  break;
1535  }
1536 
1537  domain = ub - lb;
1538  delta = REALABS(consdata->vals[v]) * domain;
1539 
1540  if( delta > consdata->maxactdelta )
1541  {
1542  consdata->maxactdelta = delta;
1543  consdata->maxactdeltavar = consdata->vars[v];
1544  }
1545  }
1546 }
1547 
1548 
1549 /** updates activities for a change in a bound */
1550 static
1552  SCIP* scip, /**< SCIP data structure */
1553  SCIP_CONSDATA* consdata, /**< linear constraint data */
1554  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1555  SCIP_Real oldbound, /**< old bound of variable */
1556  SCIP_Real newbound, /**< new bound of variable */
1557  SCIP_Real val, /**< coefficient of constraint entry */
1558  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1559  SCIP_Bool global, /**< is it a global or a local bound change? */
1560  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1561  )
1562 {
1563  SCIP_Real* activity;
1564  SCIP_Real* lastactivity;
1565  int* activityposinf;
1566  int* activityneginf;
1567  int* activityposhuge;
1568  int* activityneghuge;
1569  SCIP_Real oldcontribution;
1570  SCIP_Real newcontribution;
1571  SCIP_Real delta;
1572  SCIP_Bool validact;
1573  SCIP_Bool finitenewbound;
1574  SCIP_Bool hugevalnewcont;
1575 
1576  assert(scip != NULL);
1577  assert(consdata != NULL);
1578  assert(global || (var != NULL));
1579  assert(consdata->validactivities);
1580  assert(consdata->minactivity < SCIP_INVALID);
1581  assert(consdata->maxactivity < SCIP_INVALID);
1582  assert(consdata->lastminactivity < SCIP_INVALID);
1583  assert(consdata->lastmaxactivity < SCIP_INVALID);
1584  assert(consdata->minactivityneginf >= 0);
1585  assert(consdata->minactivityposinf >= 0);
1586  assert(consdata->maxactivityneginf >= 0);
1587  assert(consdata->maxactivityposinf >= 0);
1588  assert(consdata->minactivityneghuge >= 0);
1589  assert(consdata->minactivityposhuge >= 0);
1590  assert(consdata->maxactivityneghuge >= 0);
1591  assert(consdata->maxactivityposhuge >= 0);
1592  assert(consdata->glbminactivity < SCIP_INVALID);
1593  assert(consdata->glbmaxactivity < SCIP_INVALID);
1594  assert(consdata->lastglbminactivity < SCIP_INVALID);
1595  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1596  assert(consdata->glbminactivityneginf >= 0);
1597  assert(consdata->glbminactivityposinf >= 0);
1598  assert(consdata->glbmaxactivityneginf >= 0);
1599  assert(consdata->glbmaxactivityposinf >= 0);
1600  assert(consdata->glbminactivityneghuge >= 0);
1601  assert(consdata->glbminactivityposhuge >= 0);
1602  assert(consdata->glbmaxactivityneghuge >= 0);
1603  assert(consdata->glbmaxactivityposhuge >= 0);
1604 
1605  delta = 0.0;
1606 
1607  /* we are updating global activities */
1608  if( global )
1609  {
1610  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1611  * lower bound + pos. coef: update minactivity
1612  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1613  * upper bound + pos. coef: update maxactivity
1614  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1615  */
1616  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1617  {
1618  if( val > 0.0 )
1619  {
1620  activity = &(consdata->glbminactivity);
1621  lastactivity = &(consdata->lastglbminactivity);
1622  activityposinf = &(consdata->glbminactivityposinf);
1623  activityneginf = &(consdata->glbminactivityneginf);
1624  activityposhuge = &(consdata->glbminactivityposhuge);
1625  activityneghuge = &(consdata->glbminactivityneghuge);
1626  validact = consdata->validglbminact;
1627  }
1628  else
1629  {
1630  activity = &(consdata->glbmaxactivity);
1631  lastactivity = &(consdata->lastglbmaxactivity);
1632  activityposinf = &(consdata->glbmaxactivityneginf);
1633  activityneginf = &(consdata->glbmaxactivityposinf);
1634  activityposhuge = &(consdata->glbmaxactivityposhuge);
1635  activityneghuge = &(consdata->glbmaxactivityneghuge);
1636  validact = consdata->validglbmaxact;
1637  }
1638  }
1639  else
1640  {
1641  if( val > 0.0 )
1642  {
1643  activity = &(consdata->glbmaxactivity);
1644  lastactivity = &(consdata->lastglbmaxactivity);
1645  activityposinf = &(consdata->glbmaxactivityposinf);
1646  activityneginf = &(consdata->glbmaxactivityneginf);
1647  activityposhuge = &(consdata->glbmaxactivityposhuge);
1648  activityneghuge = &(consdata->glbmaxactivityneghuge);
1649  validact = consdata->validglbmaxact;
1650  }
1651  else
1652  {
1653  activity = &(consdata->glbminactivity);
1654  lastactivity = &(consdata->lastglbminactivity);
1655  activityposinf = &(consdata->glbminactivityneginf);
1656  activityneginf = &(consdata->glbminactivityposinf);
1657  activityposhuge = &(consdata->glbminactivityposhuge);
1658  activityneghuge = &(consdata->glbminactivityneghuge);
1659  validact = consdata->validglbminact;
1660  }
1661  }
1662  }
1663  /* we are updating local activities */
1664  else
1665  {
1666  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1667  * lower bound + pos. coef: update minactivity
1668  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1669  * upper bound + pos. coef: update maxactivity
1670  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1671  */
1672  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1673  {
1674  if( val > 0.0 )
1675  {
1676  activity = &(consdata->minactivity);
1677  lastactivity = &(consdata->lastminactivity);
1678  activityposinf = &(consdata->minactivityposinf);
1679  activityneginf = &(consdata->minactivityneginf);
1680  activityposhuge = &(consdata->minactivityposhuge);
1681  activityneghuge = &(consdata->minactivityneghuge);
1682  validact = consdata->validminact;
1683  }
1684  else
1685  {
1686  activity = &(consdata->maxactivity);
1687  lastactivity = &(consdata->lastmaxactivity);
1688  activityposinf = &(consdata->maxactivityneginf);
1689  activityneginf = &(consdata->maxactivityposinf);
1690  activityposhuge = &(consdata->maxactivityposhuge);
1691  activityneghuge = &(consdata->maxactivityneghuge);
1692  validact = consdata->validmaxact;
1693  }
1694  }
1695  else
1696  {
1697  if( val > 0.0 )
1698  {
1699  activity = &(consdata->maxactivity);
1700  lastactivity = &(consdata->lastmaxactivity);
1701  activityposinf = &(consdata->maxactivityposinf);
1702  activityneginf = &(consdata->maxactivityneginf);
1703  activityposhuge = &(consdata->maxactivityposhuge);
1704  activityneghuge = &(consdata->maxactivityneghuge);
1705  validact = consdata->validmaxact;
1706  }
1707  else
1708  {
1709  activity = &(consdata->minactivity);
1710  lastactivity = &(consdata->lastminactivity);
1711  activityposinf = &(consdata->minactivityneginf);
1712  activityneginf = &(consdata->minactivityposinf);
1713  activityposhuge = &(consdata->minactivityposhuge);
1714  activityneghuge = &(consdata->minactivityneghuge);
1715  validact = consdata->validminact;
1716  }
1717  }
1718  }
1719 
1720  oldcontribution = val * oldbound;
1721  newcontribution = val * newbound;
1722  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1723  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1724 
1725  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1726  {
1727  /* old bound was +infinity */
1728  if( oldbound > 0.0 )
1729  {
1730  assert((*activityposinf) >= 1);
1731 
1732  /* we only have to do something if the new bound is not again +infinity */
1733  if( finitenewbound || newbound < 0.0 )
1734  {
1735  /* decrease the counter for positive infinite contributions */
1736  (*activityposinf)--;
1737 
1738  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1739  if( !finitenewbound && newbound < 0.0 )
1740  (*activityneginf)++;
1741  else if( hugevalnewcont )
1742  {
1743  /* if the contribution of this variable is too large, increase the counter for huge values */
1744  if( newcontribution > 0.0 )
1745  (*activityposhuge)++;
1746  else
1747  (*activityneghuge)++;
1748  }
1749  /* "normal case": just add the contribution to the activity */
1750  else
1751  delta = newcontribution;
1752  }
1753  }
1754  /* old bound was -infinity */
1755  else
1756  {
1757  assert(oldbound < 0.0);
1758  assert((*activityneginf) >= 1);
1759 
1760  /* we only have to do something ig the new bound is not again -infinity */
1761  if( finitenewbound || newbound > 0.0 )
1762  {
1763  /* decrease the counter for negative infinite contributions */
1764  (*activityneginf)--;
1765 
1766  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1767  if( !finitenewbound && newbound > 0.0 )
1768  (*activityposinf)++;
1769  else if( hugevalnewcont )
1770  {
1771  /* if the contribution of this variable is too large, increase the counter for huge values */
1772  if( newcontribution > 0.0 )
1773  (*activityposhuge)++;
1774  else
1775  (*activityneghuge)++;
1776  }
1777  /* "normal case": just add the contribution to the activity */
1778  else
1779  delta = newcontribution;
1780  }
1781  }
1782  }
1783  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1784  {
1785  /* old contribution was too large and positive */
1786  if( oldcontribution > 0.0 )
1787  {
1788  assert((*activityposhuge) >= 1);
1789 
1790  /* decrease the counter for huge positive contributions; it might be increased again later,
1791  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1792  */
1793  (*activityposhuge)--;
1794 
1795  if( !finitenewbound )
1796  {
1797  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1798  if( newbound > 0.0 )
1799  (*activityposinf)++;
1800  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1801  else
1802  (*activityneginf)++;
1803  }
1804  else if( hugevalnewcont )
1805  {
1806  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1807  if( newcontribution > 0.0 )
1808  (*activityposhuge)++;
1809  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1810  else
1811  (*activityneghuge)++;
1812  }
1813  /* "normal case": just add the contribution to the activity */
1814  else
1815  delta = newcontribution;
1816  }
1817  /* old contribution was too large and negative */
1818  else
1819  {
1820  assert(oldcontribution < 0.0);
1821  assert((*activityneghuge) >= 1);
1822 
1823  /* decrease the counter for huge negative contributions; it might be increased again later,
1824  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1825  */
1826  (*activityneghuge)--;
1827 
1828  if( !finitenewbound )
1829  {
1830  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1831  if( newbound > 0.0 )
1832  (*activityposinf)++;
1833  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1834  else
1835  (*activityneginf)++;
1836  }
1837  else if( hugevalnewcont )
1838  {
1839  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1840  if( newcontribution > 0.0 )
1841  (*activityposhuge)++;
1842  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1843  else
1844  (*activityneghuge)++;
1845  }
1846  /* "normal case": just add the contribution to the activity */
1847  else
1848  delta = newcontribution;
1849  }
1850  }
1851  /* old bound was finite and not too large */
1852  else
1853  {
1854  if( !finitenewbound )
1855  {
1856  /* if the new bound is +infinity, the old contribution has to be subtracted
1857  * and the counter for positive infinite contributions has to be increased
1858  */
1859  if( newbound > 0.0 )
1860  {
1861  (*activityposinf)++;
1862  delta = -oldcontribution;
1863  }
1864  /* if the new bound is -infinity, the old contribution has to be subtracted
1865  * and the counter for negative infinite contributions has to be increased
1866  */
1867  else
1868  {
1869  assert(newbound < 0.0 );
1870 
1871  (*activityneginf)++;
1872  delta = -oldcontribution;
1873  }
1874  }
1875  /* if the contribution of this variable is too large, increase the counter for huge values */
1876  else if( hugevalnewcont )
1877  {
1878  if( newcontribution > 0.0 )
1879  {
1880  (*activityposhuge)++;
1881  delta = -oldcontribution;
1882  }
1883  else
1884  {
1885  (*activityneghuge)++;
1886  delta = -oldcontribution;
1887  }
1888  }
1889  /* "normal case": just update the activity */
1890  else
1891  delta = newcontribution - oldcontribution;
1892  }
1893 
1894  /* update the activity, if the current value is valid and there was a change in the finite part */
1895  if( validact && (delta != 0.0) )
1896  {
1897  /* if the absolute value of the activity is increased, this is regarded as reliable,
1898  * otherwise, we check whether we can still trust the updated value
1899  */
1900  (*activity) = (*activity) + delta;
1901  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1902 
1903  if( REALABS((*lastactivity)) < REALABS(*activity) )
1904  {
1905  (*lastactivity) = (*activity);
1906  }
1907  else
1908  {
1909  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1910  {
1911  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1912  (global ? "global " : ""), (*activity));
1913 
1914  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1915  if( global )
1916  {
1917  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1918  consdata->validglbminact = FALSE;
1919  else
1920  consdata->validglbmaxact = FALSE;
1921  }
1922  else
1923  {
1924  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1925  consdata->validminact = FALSE;
1926  else
1927  consdata->validmaxact = FALSE;
1928  }
1929  }
1930  }
1931  }
1932 }
1933 
1934 /** updates minimum and maximum activity for a change in lower bound */
1935 static
1937  SCIP* scip, /**< SCIP data structure */
1938  SCIP_CONSDATA* consdata, /**< linear constraint data */
1939  SCIP_VAR* var, /**< variable that has been changed */
1940  SCIP_Real oldlb, /**< old lower bound of variable */
1941  SCIP_Real newlb, /**< new lower bound of variable */
1942  SCIP_Real val, /**< coefficient of constraint entry */
1943  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1944  )
1945 {
1946  assert(scip != NULL);
1947  assert(consdata != NULL);
1948  assert(var != NULL);
1949 
1950  if( consdata->validactivities )
1951  {
1952  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1954  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1955  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1956  }
1957 }
1958 
1959 /** updates minimum and maximum activity for a change in upper bound */
1960 static
1962  SCIP* scip, /**< SCIP data structure */
1963  SCIP_CONSDATA* consdata, /**< linear constraint data */
1964  SCIP_VAR* var, /**< variable that has been changed */
1965  SCIP_Real oldub, /**< old upper bound of variable */
1966  SCIP_Real newub, /**< new upper bound of variable */
1967  SCIP_Real val, /**< coefficient of constraint entry */
1968  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1969  )
1970 {
1971  assert(scip != NULL);
1972  assert(consdata != NULL);
1973  assert(var != NULL);
1974 
1975  if( consdata->validactivities )
1976  {
1977  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
1979  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1980  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1981  }
1982 }
1983 
1984 /** updates minimum and maximum global activity for a change in the global lower bound */
1985 static
1987  SCIP* scip, /**< SCIP data structure */
1988  SCIP_CONSDATA* consdata, /**< linear constraint data */
1989  SCIP_Real oldlb, /**< old lower bound of variable */
1990  SCIP_Real newlb, /**< new lower bound of variable */
1991  SCIP_Real val, /**< coefficient of constraint entry */
1992  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1993  )
1994 {
1995  assert(scip != NULL);
1996  assert(consdata != NULL);
1997 
1998  if( consdata->validactivities )
1999  {
2000  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2001 
2002  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2003  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2004  }
2005 }
2006 
2007 /** updates minimum and maximum global activity for a change in global upper bound */
2008 static
2010  SCIP* scip, /**< SCIP data structure */
2011  SCIP_CONSDATA* consdata, /**< linear constraint data */
2012  SCIP_Real oldub, /**< old upper bound of variable */
2013  SCIP_Real newub, /**< new upper bound of variable */
2014  SCIP_Real val, /**< coefficient of constraint entry */
2015  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2016  )
2017 {
2018  assert(scip != NULL);
2019  assert(consdata != NULL);
2020 
2021  if( consdata->validactivities )
2022  {
2023  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2024 
2025  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2026  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2027  }
2028 }
2029 
2030 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2031 static
2033  SCIP* scip, /**< SCIP data structure */
2034  SCIP_CONSDATA* consdata, /**< linear constraint data */
2035  SCIP_VAR* var, /**< variable of constraint entry */
2036  SCIP_Real val, /**< coefficient of constraint entry */
2037  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2038  )
2039 {
2040  assert(scip != NULL);
2041  assert(consdata != NULL);
2042  assert(var != NULL);
2043 
2044  /* update maximum absolute value */
2045  if( consdata->validmaxabsval )
2046  {
2047  SCIP_Real absval;
2048 
2049  assert(consdata->maxabsval < SCIP_INVALID);
2050 
2051  absval = REALABS(val);
2052  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2053  }
2054 
2055  if( consdata->validminabsval )
2056  {
2057  SCIP_Real absval;
2058 
2059  assert(consdata->minabsval < SCIP_INVALID);
2060 
2061  absval = REALABS(val);
2062  consdata->minabsval = MIN(consdata->minabsval, absval);
2063  }
2064 
2065  /* update minimal and maximal activity */
2066  if( consdata->validactivities )
2067  {
2068  assert(consdata->minactivity < SCIP_INVALID);
2069  assert(consdata->maxactivity < SCIP_INVALID);
2070  assert(consdata->glbminactivity < SCIP_INVALID);
2071  assert(consdata->glbmaxactivity < SCIP_INVALID);
2072 
2073  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2074  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2075  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2076  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2077  }
2078 }
2079 
2080 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2081 static
2083  SCIP* scip, /**< SCIP data structure */
2084  SCIP_CONSDATA* consdata, /**< linear constraint data */
2085  SCIP_VAR* var, /**< variable of constraint entry */
2086  SCIP_Real val, /**< coefficient of constraint entry */
2087  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2088  )
2089 {
2090  assert(scip != NULL);
2091  assert(consdata != NULL);
2092  assert(var != NULL);
2093 
2094  /* invalidate maximum absolute value, if this coefficient was the maximum */
2095  if( consdata->validmaxabsval )
2096  {
2097  SCIP_Real absval;
2098 
2099  absval = REALABS(val);
2100 
2101  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2102  {
2103  consdata->validmaxabsval = FALSE;
2104  consdata->maxabsval = SCIP_INVALID;
2105  }
2106  }
2107 
2108  /* invalidate minimum absolute value, if this coefficient was the minimum */
2109  if( consdata->validminabsval )
2110  {
2111  SCIP_Real absval;
2112 
2113  absval = REALABS(val);
2114 
2115  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2116  {
2117  consdata->validminabsval = FALSE;
2118  consdata->minabsval = SCIP_INVALID;
2119  }
2120  }
2121 
2122  /* update minimal and maximal activity */
2123  if( consdata->validactivities )
2124  {
2125  assert(consdata->minactivity < SCIP_INVALID);
2126  assert(consdata->maxactivity < SCIP_INVALID);
2127  assert(consdata->glbminactivity < SCIP_INVALID);
2128  assert(consdata->glbmaxactivity < SCIP_INVALID);
2129 
2130  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2131  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2132  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2133  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2134  }
2135 }
2136 
2137 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2138 static
2140  SCIP* scip, /**< SCIP data structure */
2141  SCIP_CONSDATA* consdata, /**< linear constraint data */
2142  SCIP_VAR* var, /**< variable of constraint entry */
2143  SCIP_Real oldval, /**< old coefficient of constraint entry */
2144  SCIP_Real newval, /**< new coefficient of constraint entry */
2145  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2146  )
2147 {
2148  assert(scip != NULL);
2149  assert(consdata != NULL);
2150  assert(var != NULL);
2151 
2152  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2153  assert(!SCIPisZero(scip, oldval));
2154 
2155  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2156  assert(!SCIPisZero(scip, newval));
2157 
2158  /* update maximum absolute value */
2159  if( consdata->validmaxabsval )
2160  {
2161  SCIP_Real absval;
2162 
2163  absval = REALABS(newval);
2164 
2165  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2166  {
2167  consdata->maxabsval = absval;
2168  }
2169  else
2170  {
2171  absval = REALABS(oldval);
2172 
2173  /* invalidate maximum absolute value */
2174  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2175  {
2176  consdata->validmaxabsval = FALSE;
2177  consdata->maxabsval = SCIP_INVALID;
2178  }
2179  }
2180  }
2181 
2182  /* update minimum absolute value */
2183  if( consdata->validminabsval )
2184  {
2185  SCIP_Real absval;
2186 
2187  absval = REALABS(newval);
2188 
2189  if( SCIPisLE(scip, absval, consdata->minabsval) )
2190  {
2191  consdata->minabsval = absval;
2192  }
2193  else
2194  {
2195  absval = REALABS(oldval);
2196 
2197  /* invalidate minimum absolute value */
2198  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2199  {
2200  consdata->validminabsval = FALSE;
2201  consdata->minabsval = SCIP_INVALID;
2202  }
2203  }
2204  }
2205 
2206 
2207  /* update maximum activity delta */
2208  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2209  {
2210  SCIP_Real domain;
2211  SCIP_Real delta;
2212 
2213  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2214  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2215 
2216  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2217  delta = REALABS(newval) * domain;
2218 
2219  if( delta > consdata->maxactdelta )
2220  {
2221  consdata->maxactdelta = delta;
2222  consdata->maxactdeltavar = var;
2223  }
2224  else
2225  {
2226  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2227  if( consdata->maxactdeltavar == var )
2228  consdata->maxactdelta = SCIP_INVALID;
2229  }
2230  }
2231 
2232  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2233  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2234  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2235 }
2236 
2237 /** returns the maximum absolute value of all coefficients in the constraint */
2238 static
2240  SCIP_CONSDATA* consdata /**< linear constraint data */
2241  )
2242 {
2243  assert(consdata != NULL);
2244 
2245  if( !consdata->validmaxabsval )
2246  consdataCalcMaxAbsval(consdata);
2247  assert(consdata->validmaxabsval);
2248  assert(consdata->maxabsval < SCIP_INVALID);
2249 
2250  return consdata->maxabsval;
2251 }
2252 
2253 /** returns the minimum absolute value of all coefficients in the constraint */
2254 static
2256  SCIP_CONSDATA* consdata /**< linear constraint data */
2257  )
2258 {
2259  assert(consdata != NULL);
2260 
2261  if( !consdata->validminabsval )
2262  consdataCalcMinAbsval(consdata);
2263  assert(consdata->validminabsval);
2264  assert(consdata->minabsval < SCIP_INVALID);
2265 
2266  return consdata->minabsval;
2267 }
2268 
2269 /** calculates minimum and maximum local and global activity for constraint from scratch;
2270  * additionally recalculates maximum absolute value of coefficients
2271  */
2272 static
2274  SCIP* scip, /**< SCIP data structure */
2275  SCIP_CONSDATA* consdata /**< linear constraint data */
2276  )
2277 {
2278  int i;
2279 
2280  assert(scip != NULL);
2281  assert(consdata != NULL);
2282  assert(!consdata->validactivities);
2283  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2284  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2285  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2286  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2287 
2288  consdata->validmaxabsval = TRUE;
2289  consdata->validminabsval = TRUE;
2290  consdata->validactivities = TRUE;
2291  consdata->validminact = TRUE;
2292  consdata->validmaxact = TRUE;
2293  consdata->validglbminact = TRUE;
2294  consdata->validglbmaxact = TRUE;
2295  consdata->maxabsval = 0.0;
2296  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2297  consdata->minactivity = 0.0;
2298  consdata->maxactivity = 0.0;
2299  consdata->lastminactivity = 0.0;
2300  consdata->lastmaxactivity = 0.0;
2301  consdata->minactivityneginf = 0;
2302  consdata->minactivityposinf = 0;
2303  consdata->maxactivityneginf = 0;
2304  consdata->maxactivityposinf = 0;
2305  consdata->minactivityneghuge = 0;
2306  consdata->minactivityposhuge = 0;
2307  consdata->maxactivityneghuge = 0;
2308  consdata->maxactivityposhuge = 0;
2309  consdata->glbminactivity = 0.0;
2310  consdata->glbmaxactivity = 0.0;
2311  consdata->lastglbminactivity = 0.0;
2312  consdata->lastglbmaxactivity = 0.0;
2313  consdata->glbminactivityneginf = 0;
2314  consdata->glbminactivityposinf = 0;
2315  consdata->glbmaxactivityneginf = 0;
2316  consdata->glbmaxactivityposinf = 0;
2317  consdata->glbminactivityneghuge = 0;
2318  consdata->glbminactivityposhuge = 0;
2319  consdata->glbmaxactivityneghuge = 0;
2320  consdata->glbmaxactivityposhuge = 0;
2321 
2322  for( i = 0; i < consdata->nvars; ++i )
2323  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2324 
2325  consdata->lastminactivity = consdata->minactivity;
2326  consdata->lastmaxactivity = consdata->maxactivity;
2327  consdata->lastglbminactivity = consdata->glbminactivity;
2328  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2329 }
2330 
2331 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2332  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2333  */
2334 static
2335 void getMinActivity(
2336  SCIP* scip, /**< SCIP data structure */
2337  SCIP_CONSDATA* consdata, /**< linear constraint */
2338  int posinf, /**< number of coefficients contributing pos. infinite value */
2339  int neginf, /**< number of coefficients contributing neg. infinite value */
2340  int poshuge, /**< number of coefficients contributing huge pos. value */
2341  int neghuge, /**< number of coefficients contributing huge neg. value */
2342  SCIP_Real delta, /**< value to subtract from stored minactivity
2343  * (contribution of the variable set to zero when getting residual activity) */
2344  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2345  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2346  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2347  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2348  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2349  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2350  )
2351 {
2352  assert(scip != NULL);
2353  assert(consdata != NULL);
2354  assert(posinf >= 0);
2355  assert(neginf >= 0);
2356  assert(poshuge >= 0);
2357  assert(neghuge >= 0);
2358  assert(minactivity != NULL);
2359  assert(isrelax != NULL);
2360  assert(issettoinfinity != NULL);
2361 
2362  /* if we have pos. infinite contributions, the minactivity is +infty */
2363  if( posinf > 0 )
2364  {
2365  *minactivity = SCIPinfinity(scip);
2366  *issettoinfinity = TRUE;
2367  *isrelax = FALSE;
2368  }
2369  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2370  else if( neginf > 0 )
2371  {
2372  *minactivity = -SCIPinfinity(scip);
2373  *issettoinfinity = TRUE;
2374  *isrelax = FALSE;
2375  }
2376  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2377  else if( neghuge > 0 )
2378  {
2379  *minactivity = -SCIPinfinity(scip);
2380  *issettoinfinity = TRUE;
2381  *isrelax = TRUE;
2382  }
2383  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2384  else if( !goodrelax && poshuge > 0 )
2385  {
2386  *minactivity = -SCIPinfinity(scip);
2387  *issettoinfinity = TRUE;
2388  *isrelax = TRUE;
2389  }
2390  else
2391  {
2392  SCIP_Real tmpactivity;
2393 
2394  /* recompute minactivity if it is not valid */
2395  if( global )
2396  {
2397  if( !consdata->validglbminact )
2398  consdataRecomputeGlbMinactivity(scip, consdata);
2399  assert(consdata->validglbminact);
2400 
2401  tmpactivity = consdata->glbminactivity;
2402  }
2403  else
2404  {
2405  if( !consdata->validminact )
2406  consdataRecomputeMinactivity(scip, consdata);
2407  assert(consdata->validminact);
2408 
2409  tmpactivity = consdata->minactivity;
2410  }
2411 
2412  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2413  * a feasible relaxation of the minactivity is the number of positive huge contributions
2414  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2415  */
2416  if( poshuge > 0 )
2417  {
2418  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2419  *issettoinfinity = FALSE;
2420  *isrelax = TRUE;
2421  }
2422  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2423  else
2424  {
2425  *minactivity = tmpactivity - delta;
2426  *issettoinfinity = FALSE;
2427  *isrelax = FALSE;
2428  }
2429  }
2430 }
2431 
2432 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2433  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2434  */
2435 static
2436 void getMaxActivity(
2437  SCIP* scip, /**< SCIP data structure */
2438  SCIP_CONSDATA* consdata, /**< linear constraint */
2439  int posinf, /**< number of coefficients contributing pos. infinite value */
2440  int neginf, /**< number of coefficients contributing neg. infinite value */
2441  int poshuge, /**< number of coefficients contributing huge pos. value */
2442  int neghuge, /**< number of coefficients contributing huge neg. value */
2443  SCIP_Real delta, /**< value to subtract from stored maxactivity
2444  * (contribution of the variable set to zero when getting residual activity) */
2445  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2446  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2447  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2448  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2449  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2450  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2451  )
2452 {
2453  assert(scip != NULL);
2454  assert(consdata != NULL);
2455  assert(posinf >= 0);
2456  assert(neginf >= 0);
2457  assert(poshuge >= 0);
2458  assert(neghuge >= 0);
2459  assert(maxactivity != NULL);
2460  assert(isrelax != NULL);
2461  assert(issettoinfinity != NULL);
2462 
2463  /* if we have neg. infinite contributions, the maxactivity is -infty */
2464  if( neginf > 0 )
2465  {
2466  *maxactivity = -SCIPinfinity(scip);
2467  *issettoinfinity = TRUE;
2468  *isrelax = FALSE;
2469  }
2470  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2471  else if( posinf > 0 )
2472  {
2473  *maxactivity = SCIPinfinity(scip);
2474  *issettoinfinity = TRUE;
2475  *isrelax = FALSE;
2476  }
2477  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2478  else if( poshuge > 0 )
2479  {
2480  *maxactivity = SCIPinfinity(scip);
2481  *issettoinfinity = TRUE;
2482  *isrelax = TRUE;
2483  }
2484  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2485  else if( !goodrelax && neghuge > 0 )
2486  {
2487  *maxactivity = SCIPinfinity(scip);
2488  *issettoinfinity = TRUE;
2489  *isrelax = TRUE;
2490  }
2491  else
2492  {
2493  SCIP_Real tmpactivity;
2494 
2495  /* recompute maxactivity if it is not valid */
2496  if( global )
2497  {
2498  if( !consdata->validglbmaxact )
2499  consdataRecomputeGlbMaxactivity(scip, consdata);
2500  assert(consdata->validglbmaxact);
2501 
2502  tmpactivity = consdata->glbmaxactivity;
2503  }
2504  else
2505  {
2506  if( !consdata->validmaxact )
2507  consdataRecomputeMaxactivity(scip, consdata);
2508  assert(consdata->validmaxact);
2509 
2510  tmpactivity = consdata->maxactivity;
2511  }
2512 
2513  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2514  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2515  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2516  */
2517  if( neghuge > 0 )
2518  {
2519  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2520  *issettoinfinity = FALSE;
2521  *isrelax = TRUE;
2522  }
2523  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2524  else
2525  {
2526  *maxactivity = tmpactivity - delta;
2527  *issettoinfinity = FALSE;
2528  *isrelax = FALSE;
2529  }
2530  }
2531 }
2532 
2533 /** gets activity bounds for constraint */
2534 static
2536  SCIP* scip, /**< SCIP data structure */
2537  SCIP_CONSDATA* consdata, /**< linear constraint */
2538  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2539  * relaxed acticities ignored, anyway? */
2540  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2541  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2542  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2543  * i.e. <= the exact minactivity (in case of huge contributions),
2544  * or equal to the exact minimal activity */
2545  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2546  * i.e. >= the exact maxactivity (in case of huge contributions),
2547  * or equal to the exact maximal activity */
2548  )
2549 {
2550  SCIP_Bool issettoinfinity;
2551 
2552  assert(scip != NULL);
2553  assert(consdata != NULL);
2554  assert(minactivity != NULL);
2555  assert(maxactivity != NULL);
2556 
2557  if( !consdata->validactivities )
2558  {
2559  consdataCalcActivities(scip, consdata);
2560  assert(consdata->validminact);
2561  assert(consdata->validmaxact);
2562  }
2563  assert(consdata->minactivity < SCIP_INVALID);
2564  assert(consdata->maxactivity < SCIP_INVALID);
2565  assert(consdata->minactivityneginf >= 0);
2566  assert(consdata->minactivityposinf >= 0);
2567  assert(consdata->maxactivityneginf >= 0);
2568  assert(consdata->maxactivityposinf >= 0);
2569 
2570  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2571  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2572  minactivity, minisrelax, &issettoinfinity);
2573 
2574  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2575  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2576  maxactivity, maxisrelax, &issettoinfinity);
2577 }
2578 
2579 /** calculates activity bounds for constraint after setting variable to zero */
2580 static
2582  SCIP* scip, /**< SCIP data structure */
2583  SCIP_CONSDATA* consdata, /**< linear constraint */
2584  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2585  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2586  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2587  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2588  )
2589 {
2590  SCIP_VAR* var;
2591  SCIP_Real val;
2592  SCIP_Real lb;
2593  SCIP_Real ub;
2594  int v;
2595 
2596  assert(scip != NULL);
2597  assert(consdata != NULL);
2598  assert(cancelvar != NULL);
2599  assert(resactivity != NULL);
2600 
2601  *resactivity = 0.0;
2602 
2603  for( v = 0; v < consdata->nvars; ++v )
2604  {
2605  var = consdata->vars[v];
2606  assert(var != NULL);
2607  if( var == cancelvar )
2608  continue;
2609 
2610  val = consdata->vals[v];
2611 
2612  if( useglobalbounds )
2613  {
2614  lb = SCIPvarGetLbGlobal(var);
2615  ub = SCIPvarGetUbGlobal(var);
2616  }
2617  else
2618  {
2619  lb = SCIPvarGetLbLocal(var);
2620  ub = SCIPvarGetUbLocal(var);
2621  }
2622 
2623  assert(!SCIPisZero(scip, val));
2624  assert(SCIPisLE(scip, lb, ub));
2625 
2626  if( val > 0.0 )
2627  {
2628  if( isminresact )
2629  {
2630  assert(!SCIPisInfinity(scip, -lb));
2631  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2632  *resactivity += val*lb;
2633  }
2634  else
2635  {
2636  assert(!SCIPisInfinity(scip, ub));
2637  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2638  *resactivity += val*ub;
2639  }
2640  }
2641  else
2642  {
2643  if( isminresact)
2644  {
2645  assert(!SCIPisInfinity(scip, ub));
2646  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2647  *resactivity += val*ub;
2648  }
2649  else
2650  {
2651  assert(!SCIPisInfinity(scip, -lb));
2652  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2653  *resactivity += val*lb;
2654  }
2655  }
2656  }
2657  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2658 }
2659 
2660 /** gets activity bounds for constraint after setting variable to zero */
2661 static
2663  SCIP* scip, /**< SCIP data structure */
2664  SCIP_CONSDATA* consdata, /**< linear constraint */
2665  SCIP_VAR* var, /**< variable to calculate activity residual for */
2666  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2667  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2668  * relaxed acticities ignored, anyway? */
2669  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2670  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2671  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2672  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2673  * contributions), or equal to the exact residual minactivity */
2674  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2675  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2676  * contributions), or equal to the exact residual minactivity */
2677  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2678  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2679  )
2680 {
2681  SCIP_Real minactbound;
2682  SCIP_Real maxactbound;
2683  SCIP_Real absval;
2684 
2685  assert(scip != NULL);
2686  assert(consdata != NULL);
2687  assert(var != NULL);
2688  assert(minresactivity != NULL);
2689  assert(maxresactivity != NULL);
2690  assert(minisrelax != NULL);
2691  assert(maxisrelax != NULL);
2692  assert(isminsettoinfinity != NULL);
2693  assert(ismaxsettoinfinity != NULL);
2694 
2695  /* get activity bounds of linear constraint */
2696  if( !consdata->validactivities )
2697  {
2698  consdataCalcActivities(scip, consdata);
2699  assert(consdata->validminact);
2700  assert(consdata->validmaxact);
2701  }
2702  assert(consdata->minactivity < SCIP_INVALID);
2703  assert(consdata->maxactivity < SCIP_INVALID);
2704  assert(consdata->minactivityneginf >= 0);
2705  assert(consdata->minactivityposinf >= 0);
2706  assert(consdata->maxactivityneginf >= 0);
2707  assert(consdata->maxactivityposinf >= 0);
2708  assert(consdata->minactivityneghuge >= 0);
2709  assert(consdata->minactivityposhuge >= 0);
2710  assert(consdata->maxactivityneghuge >= 0);
2711  assert(consdata->maxactivityposhuge >= 0);
2712 
2713  if( val > 0.0 )
2714  {
2715  minactbound = SCIPvarGetLbLocal(var);
2716  maxactbound = SCIPvarGetUbLocal(var);
2717  absval = val;
2718  }
2719  else
2720  {
2721  minactbound = -SCIPvarGetUbLocal(var);
2722  maxactbound = -SCIPvarGetLbLocal(var);
2723  absval = -val;
2724  }
2725 
2726  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2727  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2728  */
2729  if( SCIPisInfinity(scip, minactbound) )
2730  {
2731  assert(consdata->minactivityposinf >= 1);
2732 
2733  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2734  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2735  minresactivity, minisrelax, isminsettoinfinity);
2736  }
2737  else if( SCIPisInfinity(scip, -minactbound) )
2738  {
2739  assert(consdata->minactivityneginf >= 1);
2740 
2741  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2742  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2743  minresactivity, minisrelax, isminsettoinfinity);
2744  }
2745  else if( SCIPisHugeValue(scip, minactbound * absval) )
2746  {
2747  assert(consdata->minactivityposhuge >= 1);
2748 
2749  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2750  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2751  minresactivity, minisrelax, isminsettoinfinity);
2752  }
2753  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2754  {
2755  assert(consdata->minactivityneghuge >= 1);
2756 
2757  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2758  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2759  minresactivity, minisrelax, isminsettoinfinity);
2760  }
2761  else
2762  {
2763  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2764  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2765  minresactivity, minisrelax, isminsettoinfinity);
2766  }
2767 
2768  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2769  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2770  */
2771  if( SCIPisInfinity(scip, -maxactbound) )
2772  {
2773  assert(consdata->maxactivityneginf >= 1);
2774 
2775  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2776  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2777  maxresactivity, maxisrelax, ismaxsettoinfinity);
2778  }
2779  else if( SCIPisInfinity(scip, maxactbound) )
2780  {
2781  assert(consdata->maxactivityposinf >= 1);
2782 
2783  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2784  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2785  maxresactivity, maxisrelax, ismaxsettoinfinity);
2786  }
2787  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2788  {
2789  assert(consdata->maxactivityposhuge >= 1);
2790 
2791  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2792  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2793  maxresactivity, maxisrelax, ismaxsettoinfinity);
2794  }
2795  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2796  {
2797  assert(consdata->maxactivityneghuge >= 1);
2798 
2799  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2800  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2801  maxresactivity, maxisrelax, ismaxsettoinfinity);
2802  }
2803  else
2804  {
2805  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2806  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2807  maxresactivity, maxisrelax, ismaxsettoinfinity);
2808  }
2809 }
2810 
2811 /** gets global activity bounds for constraint */
2812 static
2814  SCIP* scip, /**< SCIP data structure */
2815  SCIP_CONSDATA* consdata, /**< linear constraint */
2816  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2817  * relaxed acticities ignored, anyway? */
2818  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2819  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2820  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2821  * i.e. <= the exact minactivity (in case of huge contributions),
2822  * or equal to the exact minimal activity */
2823  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2824  * i.e. >= the exact maxactivity (in case of huge contributions),
2825  * or equal to the exact maximal activity */
2826  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2827  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2828  )
2829 {
2830  assert(scip != NULL);
2831  assert(consdata != NULL);
2832  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2833  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2834 
2835  if( !consdata->validactivities )
2836  {
2837  consdataCalcActivities(scip, consdata);
2838  assert(consdata->validglbminact);
2839  assert(consdata->validglbmaxact);
2840  }
2841  assert(consdata->glbminactivity < SCIP_INVALID);
2842  assert(consdata->glbmaxactivity < SCIP_INVALID);
2843  assert(consdata->glbminactivityneginf >= 0);
2844  assert(consdata->glbminactivityposinf >= 0);
2845  assert(consdata->glbmaxactivityneginf >= 0);
2846  assert(consdata->glbmaxactivityposinf >= 0);
2847  assert(consdata->glbminactivityneghuge >= 0);
2848  assert(consdata->glbminactivityposhuge >= 0);
2849  assert(consdata->glbmaxactivityneghuge >= 0);
2850  assert(consdata->glbmaxactivityposhuge >= 0);
2851 
2852  if( glbminactivity != NULL )
2853  {
2854  assert(isminsettoinfinity != NULL);
2855  assert(minisrelax != NULL);
2856 
2857  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2858  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2859  glbminactivity, minisrelax, isminsettoinfinity);
2860  }
2861 
2862  if( glbmaxactivity != NULL )
2863  {
2864  assert(ismaxsettoinfinity != NULL);
2865  assert(maxisrelax != NULL);
2866 
2867  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2868  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2869  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2870  }
2871 }
2872 
2873 /** gets global activity bounds for constraint after setting variable to zero */
2874 static
2876  SCIP* scip, /**< SCIP data structure */
2877  SCIP_CONSDATA* consdata, /**< linear constraint */
2878  SCIP_VAR* var, /**< variable to calculate activity residual for */
2879  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2880  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2881  * relaxed acticities ignored, anyway? */
2882  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2883  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2884  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2885  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2886  * contributions), or equal to the exact residual minactivity */
2887  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2888  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2889  * contributions), or equal to the exact residual minactivity */
2890  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2891  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2892  )
2893 {
2894  SCIP_Real minactbound;
2895  SCIP_Real maxactbound;
2896  SCIP_Real absval;
2897 
2898  assert(scip != NULL);
2899  assert(consdata != NULL);
2900  assert(var != NULL);
2901  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2902  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2903 
2904  /* get activity bounds of linear constraint */
2905  if( !consdata->validactivities )
2906  consdataCalcActivities(scip, consdata);
2907 
2908  assert(consdata->glbminactivity < SCIP_INVALID);
2909  assert(consdata->glbmaxactivity < SCIP_INVALID);
2910  assert(consdata->glbminactivityneginf >= 0);
2911  assert(consdata->glbminactivityposinf >= 0);
2912  assert(consdata->glbmaxactivityneginf >= 0);
2913  assert(consdata->glbmaxactivityposinf >= 0);
2914 
2915  if( val > 0.0 )
2916  {
2917  minactbound = SCIPvarGetLbGlobal(var);
2918  maxactbound = SCIPvarGetUbGlobal(var);
2919  absval = val;
2920  }
2921  else
2922  {
2923  minactbound = -SCIPvarGetUbGlobal(var);
2924  maxactbound = -SCIPvarGetLbGlobal(var);
2925  absval = -val;
2926  }
2927 
2928  if( minresactivity != NULL )
2929  {
2930  assert(isminsettoinfinity != NULL);
2931  assert(minisrelax != NULL);
2932 
2933  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2934  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2935  */
2936  if( SCIPisInfinity(scip, minactbound) )
2937  {
2938  assert(consdata->glbminactivityposinf >= 1);
2939 
2940  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2941  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2942  minresactivity, minisrelax, isminsettoinfinity);
2943  }
2944  else if( SCIPisInfinity(scip, -minactbound) )
2945  {
2946  assert(consdata->glbminactivityneginf >= 1);
2947 
2948  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2949  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2950  minresactivity, minisrelax, isminsettoinfinity);
2951  }
2952  else if( SCIPisHugeValue(scip, minactbound * absval) )
2953  {
2954  assert(consdata->glbminactivityposhuge >= 1);
2955 
2956  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2957  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2958  minresactivity, minisrelax, isminsettoinfinity);
2959  }
2960  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2961  {
2962  assert(consdata->glbminactivityneghuge >= 1);
2963 
2964  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2965  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2966  minresactivity, minisrelax, isminsettoinfinity);
2967  }
2968  else
2969  {
2970  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2971  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2972  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
2973  }
2974  }
2975 
2976  if( maxresactivity != NULL )
2977  {
2978  assert(ismaxsettoinfinity != NULL);
2979  assert(maxisrelax != NULL);
2980 
2981  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2982  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2983  */
2984  if( SCIPisInfinity(scip, -maxactbound) )
2985  {
2986  assert(consdata->glbmaxactivityneginf >= 1);
2987 
2988  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2989  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2990  maxresactivity, maxisrelax, ismaxsettoinfinity);
2991  }
2992  else if( SCIPisInfinity(scip, maxactbound) )
2993  {
2994  assert(consdata->glbmaxactivityposinf >= 1);
2995 
2996  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2997  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2998  maxresactivity, maxisrelax, ismaxsettoinfinity);
2999  }
3000  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3001  {
3002  assert(consdata->glbmaxactivityposhuge >= 1);
3003 
3004  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3005  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3006  maxresactivity, maxisrelax, ismaxsettoinfinity);
3007  }
3008  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3009  {
3010  assert(consdata->glbmaxactivityneghuge >= 1);
3011 
3012  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3013  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3014  maxresactivity, maxisrelax, ismaxsettoinfinity);
3015  }
3016  else
3017  {
3018  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3019  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3020  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3021  }
3022  }
3023 }
3024 
3025 /** calculates the activity of the linear constraint for given solution */
3026 static
3028  SCIP* scip, /**< SCIP data structure */
3029  SCIP_CONSDATA* consdata, /**< linear constraint data */
3030  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3031  )
3032 {
3033  SCIP_Real activity;
3034 
3035  assert(scip != NULL);
3036  assert(consdata != NULL);
3037 
3038  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3039  activity = consdataComputePseudoActivity(scip, consdata);
3040  else
3041  {
3042  SCIP_Real solval;
3043  int nposinf;
3044  int nneginf;
3045  SCIP_Bool negsign;
3046  int v;
3047 
3048  activity = 0.0;
3049  nposinf = 0;
3050  nneginf = 0;
3051 
3052  for( v = 0; v < consdata->nvars; ++v )
3053  {
3054  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3055 
3056  if( consdata->vals[v] < 0 )
3057  negsign = TRUE;
3058  else
3059  negsign = FALSE;
3060 
3061  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3062  ++nposinf;
3063  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3064  ++nneginf;
3065  else
3066  activity += consdata->vals[v] * solval;
3067  }
3068  assert(nneginf >= 0 && nposinf >= 0);
3069 
3070  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3071 
3072  /* check for amount of infinity values and correct the activity */
3073  if( nposinf > 0 && nneginf > 0 )
3074  activity = (consdata->rhs + consdata->lhs) / 2;
3075  else if( nposinf > 0 )
3076  activity = SCIPinfinity(scip);
3077  else if( nneginf > 0 )
3078  activity = -SCIPinfinity(scip);
3079 
3080  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3081  }
3082 
3083  if( activity == SCIP_INVALID ) /*lint !e777*/
3084  return activity;
3085  else if( activity < 0 )
3086  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3087  else
3088  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3089 
3090  return activity;
3091 }
3092 
3093 /** calculates the feasibility of the linear constraint for given solution */
3094 static
3096  SCIP* scip, /**< SCIP data structure */
3097  SCIP_CONSDATA* consdata, /**< linear constraint data */
3098  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3099  )
3100 {
3101  SCIP_Real activity;
3102 
3103  assert(scip != NULL);
3104  assert(consdata != NULL);
3105 
3106  activity = consdataGetActivity(scip, consdata, sol);
3107 
3108  if( activity == SCIP_INVALID ) /*lint !e777*/
3109  return -SCIPinfinity(scip);
3110 
3111  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3113 
3114 /** updates bit signatures after adding a single coefficient */
3115 static
3117  SCIP_CONSDATA* consdata, /**< linear constraint data */
3118  int pos /**< position of coefficient to update signatures for */
3119  )
3120 {
3121  uint64_t varsignature;
3122  SCIP_Real lb;
3123  SCIP_Real ub;
3124  SCIP_Real val;
3125 
3126  assert(consdata != NULL);
3127  assert(consdata->validsignature);
3128 
3129  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3130  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3131  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3132  val = consdata->vals[pos];
3133  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3134  consdata->possignature |= varsignature;
3135  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3136  consdata->negsignature |= varsignature;
3137 }
3138 
3139 /** calculates the bit signatures of the given constraint data */
3140 static
3142  SCIP_CONSDATA* consdata /**< linear constraint data */
3143  )
3144 {
3145  assert(consdata != NULL);
3146 
3147  if( !consdata->validsignature )
3148  {
3149  int i;
3150 
3151  consdata->validsignature = TRUE;
3152  consdata->possignature = 0;
3153  consdata->negsignature = 0;
3154  for( i = 0; i < consdata->nvars; ++i )
3155  consdataUpdateSignatures(consdata, i);
3156  }
3157 }
3159 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3160 static
3161 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3162 { /*lint --e{715}*/
3163  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3164 
3165  assert(consdata != NULL);
3166  assert(0 <= ind1 && ind1 < consdata->nvars);
3167  assert(0 <= ind2 && ind2 < consdata->nvars);
3168 
3169  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3170 }
3171 
3172 /** permutes the constraint's variables according to a given permutation. */
3173 static
3174 void permSortConsdata(
3175  SCIP_CONSDATA* consdata, /**< the constraint data */
3176  int* perm, /**< the target permutation */
3177  int nvars /**< the number of variables */
3178  )
3179 { /*lint --e{715}*/
3180  SCIP_VAR* varv;
3181  SCIP_EVENTDATA* eventdatav;
3182  SCIP_Real valv;
3183  int v;
3184  int i;
3185  int nexti;
3186 
3187  assert(perm != NULL);
3188  assert(consdata != NULL);
3189 
3190  /* permute the variables in the linear constraint according to the target permutation */
3191  eventdatav = NULL;
3192  for( v = 0; v < nvars; ++v )
3193  {
3194  if( perm[v] != v )
3195  {
3196  varv = consdata->vars[v];
3197  valv = consdata->vals[v];
3198  if( consdata->eventdata != NULL )
3199  eventdatav = consdata->eventdata[v];
3200  i = v;
3201  do
3202  {
3203  assert(0 <= perm[i] && perm[i] < nvars);
3204  assert(perm[i] != i);
3205  consdata->vars[i] = consdata->vars[perm[i]];
3206  consdata->vals[i] = consdata->vals[perm[i]];
3207  if( consdata->eventdata != NULL )
3208  {
3209  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3210  consdata->eventdata[i]->varpos = i;
3211  }
3212  nexti = perm[i];
3213  perm[i] = i;
3214  i = nexti;
3215  }
3216  while( perm[i] != v );
3217  consdata->vars[i] = varv;
3218  consdata->vals[i] = valv;
3219  if( consdata->eventdata != NULL )
3220  {
3221  consdata->eventdata[i] = eventdatav;
3222  consdata->eventdata[i]->varpos = i;
3223  }
3224  perm[i] = i;
3225  }
3226  }
3227 #ifdef SCIP_DEBUG
3228  /* check sorting */
3229  for( v = 0; v < nvars; ++v )
3230  {
3231  assert(perm[v] == v);
3232  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3233  }
3234 #endif
3235 }
3236 
3237 /** sorts linear constraint's variables depending on the stage of the solving process:
3238  * - during PRESOLVING
3239  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3240  * and the variables of the same type by non-decreasing variable index
3241  *
3242  * - during SOLVING
3243  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3244  * This fastens the propagation time of the constraint handler.
3245  */
3246 static
3248  SCIP* scip, /**< SCIP data structure */
3249  SCIP_CONSDATA* consdata /**< linear constraint data */
3250  )
3251 {
3252  assert(scip != NULL);
3253  assert(consdata != NULL);
3254 
3255  /* check if there are variables for sorting */
3256  if( consdata->nvars <= 1 )
3257  {
3258  consdata->sorted = TRUE;
3259  consdata->binvarssorted = TRUE;
3260  }
3261  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3262  {
3263  int* perm;
3265  /* get temporary memory to store the sorted permutation */
3266  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3267 
3268  /* call sorting method */
3269  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3270 
3271  permSortConsdata(consdata, perm, consdata->nvars);
3272 
3273  /* free temporary memory */
3274  SCIPfreeBufferArray(scip, &perm);
3275 
3276  consdata->sorted = TRUE;
3277  consdata->binvarssorted = FALSE;
3278  }
3279  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3280  {
3281  SCIP_EVENTDATA** eventdata;
3282  SCIP_VAR** vars;
3283  SCIP_Real* vals;
3284  int nvars;
3285  int v;
3286  int lastbin;
3287 
3288  nvars = consdata->nvars;
3289  vars = consdata->vars;
3290  vals = consdata->vals;
3291  eventdata = consdata->eventdata;
3292  assert(vars != NULL || nvars == 0);
3293  assert(vals != NULL || nvars == 0);
3294 
3295  lastbin = 0;
3296  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3297  for( v = 0; v < nvars; ++v )
3298  {
3299  assert( vars != NULL); /* for flexelint */
3300  assert( vals != NULL); /* for flexelint */
3301  if( SCIPvarIsBinary(vars[v]) )
3302  {
3303  /* swap variable at the end of the binary variables, if necessary */
3304  if( lastbin < v )
3305  {
3306  SCIP_VAR* tmpvar;
3307  SCIP_Real tmpval;
3308 
3309  tmpvar = vars[lastbin];
3310  tmpval = vals[lastbin];
3311 
3312  vars[lastbin] = vars[v];
3313  vals[lastbin] = vals[v];
3314 
3315  vars[v] = tmpvar;
3316  vals[v] = tmpval;
3317 
3318  if( eventdata != NULL )
3319  {
3320  SCIP_EVENTDATA* tmpeventdata;
3321 
3322  tmpeventdata = eventdata[lastbin];
3323  eventdata[lastbin] = eventdata[v];
3324  eventdata[lastbin]->varpos = lastbin;
3325  eventdata[v] = tmpeventdata;
3326  eventdata[v]->varpos = v;
3327  }
3328  assert(SCIPvarIsBinary(vars[lastbin]));
3329  }
3330 #ifndef NDEBUG
3331  else
3332  assert(lastbin == v);
3333 #endif
3334  ++lastbin;
3335  }
3336  }
3337  consdata->nbinvars = lastbin;
3338 
3339 #ifndef NDEBUG
3340  /* check sorting */
3341  for( v = 0; v < nvars; ++v )
3342  {
3343  assert(vars != NULL); /* for flexelint */
3344  assert(eventdata == NULL || eventdata[v]->varpos == v);
3345  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3346  }
3347 #endif
3348 
3349  if( consdata->nbinvars > 1 )
3350  {
3351  SCIP_Real* absvals;
3352  int* perm;
3353 
3354  assert(lastbin == consdata->nbinvars);
3355  assert(lastbin <= nvars);
3356  assert(vals != NULL);
3357 
3358  /* initialize absolute coefficients and the target permutation for binary variables */
3359  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3360  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3361 
3362  for( v = 0; v < lastbin; ++v )
3363  {
3364  absvals[v] = ABS(vals[v]);
3365  perm[v] = v;
3366  }
3367 
3368  /* execute the sorting */
3369  SCIPsortDownRealInt(absvals, perm, lastbin);
3370 
3371  permSortConsdata(consdata, perm, lastbin);
3372 
3373  /* free temporary arrays */
3374  SCIPfreeBufferArray(scip, &perm);
3375  SCIPfreeBufferArray(scip, &absvals);
3376  }
3377  consdata->binvarssorted = TRUE;
3378 
3379  /* presolve sorting cannot be guaranteed after binary sorting */
3380  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3381  }
3382  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3383  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3384 
3385  return SCIP_OKAY;
3386 }
3387 
3388 
3389 /*
3390  * local linear constraint handler methods
3391  */
3392 
3393 /** sets left hand side of linear constraint */
3394 static
3396  SCIP* scip, /**< SCIP data structure */
3397  SCIP_CONS* cons, /**< linear constraint */
3398  SCIP_Real lhs /**< new left hand side */
3399  )
3400 {
3401  SCIP_CONSDATA* consdata;
3402 
3403  assert(scip != NULL);
3404  assert(cons != NULL);
3405  assert(!SCIPisInfinity(scip, lhs));
3406 
3407  /* adjust value to not be smaller than -inf */
3408  if ( SCIPisInfinity(scip, -lhs) )
3409  lhs = -SCIPinfinity(scip);
3410 
3411  consdata = SCIPconsGetData(cons);
3412  assert(consdata != NULL);
3413  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3414  assert(!SCIPisInfinity(scip, consdata->lhs));
3415 
3416  /* check whether the side is not changed */
3417  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3418  return SCIP_OKAY;
3419 
3420  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3421  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3422  {
3423  consdata->rhs = lhs;
3424  assert(consdata->row == NULL);
3425  }
3426 
3427  /* if necessary, update the rounding locks of variables */
3428  if( SCIPconsIsLocked(cons) )
3429  {
3430  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3431  {
3432  SCIP_VAR** vars;
3433  SCIP_Real* vals;
3434  int v;
3435 
3436  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3437  vars = consdata->vars;
3438  vals = consdata->vals;
3439 
3440  for( v = 0; v < consdata->nvars; ++v )
3441  {
3442  assert(vars[v] != NULL);
3443  assert(!SCIPisZero(scip, vals[v]));
3444 
3445  if( SCIPisPositive(scip, vals[v]) )
3446  {
3447  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3448  }
3449  else
3450  {
3451  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3452  }
3453  }
3454  }
3455  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3456  {
3457  SCIP_VAR** vars;
3458  SCIP_Real* vals;
3459  int v;
3460 
3461  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3462  vars = consdata->vars;
3463  vals = consdata->vals;
3464 
3465  for( v = 0; v < consdata->nvars; ++v )
3466  {
3467  assert(vars[v] != NULL);
3468  assert(!SCIPisZero(scip, vals[v]));
3469 
3470  if( SCIPisPositive(scip, vals[v]) )
3471  {
3472  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3473  }
3474  else
3475  {
3476  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3477  }
3478  }
3479  }
3480  }
3481 
3482  /* 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 */
3483  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3484  {
3485  consdata->boundstightened = 0;
3486  consdata->presolved = FALSE;
3487  consdata->cliquesadded = FALSE;
3488  consdata->implsadded = FALSE;
3489 
3490  /* mark the constraint for propagation */
3491  if( SCIPconsIsTransformed(cons) )
3492  {
3493  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3494  }
3495  }
3496 
3497  /* set new left hand side and update constraint data */
3498  consdata->lhs = lhs;
3499  consdata->changed = TRUE;
3500  consdata->normalized = FALSE;
3501  consdata->upgradetried = FALSE;
3502  consdata->rangedrowpropagated = 0;
3503 
3504 
3505  /* update the lhs of the LP row */
3506  if( consdata->row != NULL )
3507  {
3508  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3509  }
3510 
3511  return SCIP_OKAY;
3512 }
3513 
3514 /** sets right hand side of linear constraint */
3515 static
3517  SCIP* scip, /**< SCIP data structure */
3518  SCIP_CONS* cons, /**< linear constraint */
3519  SCIP_Real rhs /**< new right hand side */
3520  )
3521 {
3522  SCIP_CONSDATA* consdata;
3523 
3524  assert(scip != NULL);
3525  assert(cons != NULL);
3526  assert(!SCIPisInfinity(scip, -rhs));
3527 
3528  /* adjust value to not be larger than inf */
3529  if ( SCIPisInfinity(scip, rhs) )
3530  rhs = SCIPinfinity(scip);
3531 
3532  consdata = SCIPconsGetData(cons);
3533  assert(consdata != NULL);
3534  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3535  assert(!SCIPisInfinity(scip, -consdata->rhs));
3536 
3537  /* check whether the side is not changed */
3538  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3539  return SCIP_OKAY;
3540 
3541  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3542  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3543  {
3544  consdata->lhs = rhs;
3545  assert(consdata->row == NULL);
3546  }
3547 
3548  /* if necessary, update the rounding locks of variables */
3549  if( SCIPconsIsLocked(cons) )
3550  {
3551  assert(SCIPconsIsTransformed(cons));
3552 
3553  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3554  {
3555  SCIP_VAR** vars;
3556  SCIP_Real* vals;
3557  int v;
3558 
3559  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3560  vars = consdata->vars;
3561  vals = consdata->vals;
3562 
3563  for( v = 0; v < consdata->nvars; ++v )
3564  {
3565  assert(vars[v] != NULL);
3566  assert(!SCIPisZero(scip, vals[v]));
3567 
3568  if( SCIPisPositive(scip, vals[v]) )
3569  {
3570  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3571  }
3572  else
3573  {
3574  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3575  }
3576  }
3577  }
3578  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3579  {
3580  SCIP_VAR** vars;
3581  SCIP_Real* vals;
3582  int v;
3583 
3584  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3585  vars = consdata->vars;
3586  vals = consdata->vals;
3587 
3588  for( v = 0; v < consdata->nvars; ++v )
3589  {
3590  assert(vars[v] != NULL);
3591  assert(!SCIPisZero(scip, vals[v]));
3592 
3593  if( SCIPisPositive(scip, vals[v]) )
3594  {
3595  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3596  }
3597  else
3598  {
3599  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3600  }
3601  }
3602  }
3603  }
3604 
3605  /* 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 */
3606  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3607  {
3608  consdata->boundstightened = 0;
3609  consdata->presolved = FALSE;
3610  consdata->cliquesadded = FALSE;
3611  consdata->implsadded = FALSE;
3612 
3613  /* mark the constraint for propagation */
3614  if( SCIPconsIsTransformed(cons) )
3615  {
3616  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3617  }
3618  }
3619 
3620  /* set new right hand side and update constraint data */
3621  consdata->rhs = rhs;
3622  consdata->changed = TRUE;
3623  consdata->normalized = FALSE;
3624  consdata->upgradetried = FALSE;
3625  consdata->rangedrowpropagated = 0;
3626 
3627  /* update the rhs of the LP row */
3628  if( consdata->row != NULL )
3629  {
3630  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3631  }
3632 
3633  return SCIP_OKAY;
3634 }
3635 
3636 /** adds coefficient in linear constraint */
3637 static
3639  SCIP* scip, /**< SCIP data structure */
3640  SCIP_CONS* cons, /**< linear constraint */
3641  SCIP_VAR* var, /**< variable of constraint entry */
3642  SCIP_Real val /**< coefficient of constraint entry */
3643  )
3644 {
3645  SCIP_CONSDATA* consdata;
3646  SCIP_Bool transformed;
3647 
3648  assert(scip != NULL);
3649  assert(cons != NULL);
3650  assert(var != NULL);
3651 
3652  /* ignore coefficient if it is nearly zero */
3653  if( SCIPisZero(scip, val) )
3654  return SCIP_OKAY;
3656  consdata = SCIPconsGetData(cons);
3657  assert(consdata != NULL);
3658 
3659  /* are we in the transformed problem? */
3660  transformed = SCIPconsIsTransformed(cons);
3661 
3662  /* always use transformed variables in transformed constraints */
3663  if( transformed )
3664  {
3665  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3666  }
3667  assert(var != NULL);
3668  assert(transformed == SCIPvarIsTransformed(var));
3669 
3670  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3671  consdata->vars[consdata->nvars] = var;
3672  consdata->vals[consdata->nvars] = val;
3673  consdata->nvars++;
3674 
3675  /* capture variable */
3676  SCIP_CALL( SCIPcaptureVar(scip, var) );
3677 
3678  /* if we are in transformed problem, the variable needs an additional event data */
3679  if( transformed )
3680  {
3681  if( consdata->eventdata != NULL )
3682  {
3683  SCIP_CONSHDLR* conshdlr;
3684  SCIP_CONSHDLRDATA* conshdlrdata;
3685 
3686  /* check for event handler */
3687  conshdlr = SCIPconsGetHdlr(cons);
3688  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3689  assert(conshdlrdata != NULL);
3690  assert(conshdlrdata->eventhdlr != NULL);
3691 
3692  /* initialize eventdata array */
3693  consdata->eventdata[consdata->nvars-1] = NULL;
3694 
3695  /* catch bound change events of variable */
3696  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3697  }
3698 
3699  /* update minimum and maximum activities */
3700  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3701 
3702  /* update maximum activity delta */
3703  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3704  {
3705  SCIP_Real lb;
3706  SCIP_Real ub;
3707 
3708  lb = SCIPvarGetLbLocal(var);
3709  ub = SCIPvarGetUbLocal(var);
3710 
3711  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3712  {
3713  consdata->maxactdelta = SCIPinfinity(scip);
3714  consdata->maxactdeltavar = var;
3715  }
3716  else
3717  {
3718  SCIP_Real domain = ub - lb;
3719  SCIP_Real delta = REALABS(val) * domain;
3720 
3721  if( delta > consdata->maxactdelta )
3722  {
3723  consdata->maxactdelta = delta;
3724  consdata->maxactdeltavar = var;
3725  }
3726  }
3727  }
3728  }
3729 
3730  /* install rounding locks for new variable */
3731  SCIP_CALL( lockRounding(scip, cons, var, val) );
3732 
3733  /* mark the constraint for propagation */
3734  if( transformed )
3735  {
3736  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3737  }
3738 
3739  consdata->boundstightened = 0;
3740  consdata->presolved = FALSE;
3741  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3742 
3743  if( consdata->validsignature )
3744  consdataUpdateSignatures(consdata, consdata->nvars-1);
3745 
3746  consdata->changed = TRUE;
3747  consdata->normalized = FALSE;
3748  consdata->upgradetried = FALSE;
3749  consdata->cliquesadded = FALSE;
3750  consdata->implsadded = FALSE;
3751  consdata->rangedrowpropagated = 0;
3752 
3753  if( consdata->nvars == 1 )
3754  {
3755  consdata->binvarssorted = TRUE;
3756  consdata->sorted = TRUE;
3757  consdata->merged = TRUE;
3758  }
3759  else
3760  {
3761  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3762  consdata->sorted = consdata->sorted
3763  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3764  consdata->merged = FALSE;
3765  }
3766 
3767  /* update hascontvar and hasnonbinvar flags */
3768  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3769  {
3770  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3771 
3772  if( vartype != SCIP_VARTYPE_BINARY )
3773  {
3774  consdata->hasnonbinvar = TRUE;
3775 
3776  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3777  consdata->hascontvar = TRUE;
3778  }
3779  }
3780 
3781  /* add the new coefficient to the LP row */
3782  if( consdata->row != NULL )
3783  {
3784  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3785  }
3786 
3787  return SCIP_OKAY;
3788 }
3789 
3790 /** deletes coefficient at given position from linear constraint data */
3791 static
3793  SCIP* scip, /**< SCIP data structure */
3794  SCIP_CONS* cons, /**< linear constraint */
3795  int pos /**< position of coefficient to delete */
3796  )
3797 {
3798  SCIP_CONSDATA* consdata;
3799  SCIP_VAR* var;
3800  SCIP_Real val;
3801 
3802  assert(scip != NULL);
3803  assert(cons != NULL);
3804 
3805  consdata = SCIPconsGetData(cons);
3806  assert(consdata != NULL);
3807  assert(0 <= pos && pos < consdata->nvars);
3808 
3809  var = consdata->vars[pos];
3810  val = consdata->vals[pos];
3811  assert(var != NULL);
3812 
3813  /* remove rounding locks for deleted variable */
3814  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3815 
3816  /* if we are in transformed problem, delete the event data of the variable */
3817  if( SCIPconsIsTransformed(cons) )
3818  {
3819  SCIP_CONSHDLR* conshdlr;
3820  SCIP_CONSHDLRDATA* conshdlrdata;
3821 
3822  /* check for event handler */
3823  conshdlr = SCIPconsGetHdlr(cons);
3824  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3825  assert(conshdlrdata != NULL);
3826  assert(conshdlrdata->eventhdlr != NULL);
3827 
3828  /* drop bound change events of variable */
3829  if( consdata->eventdata != NULL )
3830  {
3831  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3832  assert(consdata->eventdata[pos] == NULL);
3833  }
3834  }
3835 
3836  /* move the last variable to the free slot */
3837  if( pos != consdata->nvars-1 )
3838  {
3839  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3840 
3841  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3842  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3843 
3844  if( consdata->eventdata != NULL )
3845  {
3846  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3847  assert(consdata->eventdata[pos] != NULL);
3848  consdata->eventdata[pos]->varpos = pos;
3849  }
3850  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3851  }
3852  consdata->nvars--;
3853 
3854  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3855  * of the remaining variable, or give exactly 0.0)
3856  */
3857  if( consdata->nvars <= 1 )
3858  consdataInvalidateActivities(consdata);
3859  else
3860  {
3861  if( SCIPconsIsTransformed(cons) )
3862  {
3863  /* if we are in transformed problem, update minimum and maximum activities */
3864  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3865 
3866  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3867  * delta needs to be recalculated on the next real propagation
3868  */
3869  if( consdata->maxactdeltavar == var )
3870  {
3871  consdata->maxactdelta = SCIP_INVALID;
3872  consdata->maxactdeltavar = NULL;
3873  }
3874  }
3875  }
3876 
3877  /* mark the constraint for propagation */
3878  if( SCIPconsIsTransformed(cons) )
3879  {
3880  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3881  }
3882 
3883  consdata->boundstightened = 0;
3884  consdata->presolved = FALSE;
3885  consdata->validsignature = FALSE;
3886  consdata->changed = TRUE;
3887  consdata->normalized = FALSE;
3888  consdata->upgradetried = FALSE;
3889  consdata->cliquesadded = FALSE;
3890  consdata->implsadded = FALSE;
3891  consdata->rangedrowpropagated = 0;
3892 
3893  /* check if hasnonbinvar flag might be incorrect now */
3894  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3895  {
3896  consdata->hasnonbinvalid = FALSE;
3897  }
3898 
3899  /* delete coefficient from the LP row */
3900  if( consdata->row != NULL )
3901  {
3902  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3903  }
3904 
3905  /* release variable */
3906  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3907 
3908  return SCIP_OKAY;
3909 }
3910 
3911 /** changes coefficient value at given position of linear constraint data */
3912 static
3914  SCIP* scip, /**< SCIP data structure */
3915  SCIP_CONS* cons, /**< linear constraint */
3916  int pos, /**< position of coefficient to delete */
3917  SCIP_Real newval /**< new value of coefficient */
3918  )
3919 {
3920  SCIP_CONSDATA* consdata;
3921  SCIP_VAR* var;
3922  SCIP_Real val;
3923 
3924  assert(scip != NULL);
3925  assert(cons != NULL);
3926  assert(!SCIPisZero(scip, newval));
3927 
3928  consdata = SCIPconsGetData(cons);
3929  assert(consdata != NULL);
3930  assert(0 <= pos && pos < consdata->nvars);
3931  assert(!SCIPisZero(scip, newval));
3932 
3933  var = consdata->vars[pos];
3934  val = consdata->vals[pos];
3935  assert(var != NULL);
3936  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3937 
3938  /* if necessary, update the rounding locks of the variable */
3939  if( SCIPconsIsLocked(cons) && newval * val < 0.0 )
3940  {
3941  assert(SCIPconsIsTransformed(cons));
3942 
3943  /* remove rounding locks for variable with old coefficient */
3944  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3945 
3946  /* install rounding locks for variable with new coefficient */
3947  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3948  }
3949 
3950  /* change the value */
3951  consdata->vals[pos] = newval;
3952 
3953  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3954 
3955  /* update minimum and maximum activities */
3956  if( SCIPconsIsTransformed(cons) )
3957  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3958 
3959  /* mark the constraint for propagation */
3960  if( SCIPconsIsTransformed(cons) )
3961  {
3962  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3963  }
3964 
3965  consdata->boundstightened = 0;
3966  consdata->presolved = FALSE;
3967  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3968  consdata->changed = TRUE;
3969  consdata->normalized = FALSE;
3970  consdata->upgradetried = FALSE;
3971  consdata->cliquesadded = FALSE;
3972  consdata->implsadded = FALSE;
3973  consdata->rangedrowpropagated = 0;
3974 
3975  return SCIP_OKAY;
3976 }
3977 
3978 /** scales a linear constraint with a constant scalar */
3979 static
3981  SCIP* scip, /**< SCIP data structure */
3982  SCIP_CONS* cons, /**< linear constraint to scale */
3983  SCIP_Real scalar /**< value to scale constraint with */
3984  )
3985 {
3986  SCIP_CONSDATA* consdata;
3987  SCIP_Real newval;
3988  SCIP_Real absscalar;
3989  int i;
3990 
3991  assert(scip != NULL);
3992  assert(cons != NULL);
3993 
3994  consdata = SCIPconsGetData(cons);
3995  assert(consdata != NULL);
3996  assert(consdata->row == NULL);
3997  assert(!SCIPisEQ(scip, scalar, 1.0));
3998 
3999  /* scale the coefficients */
4000  for( i = consdata->nvars - 1; i >= 0; --i )
4001  {
4002  newval = scalar * consdata->vals[i];
4003 
4004  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4005  * flooring down our new value
4006  */
4007  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4008  newval = SCIPfeasFloor(scip, newval + 0.5);
4009 
4010  if( SCIPisZero(scip, newval) )
4011  {
4012  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4013  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4014  SCIP_CALL( delCoefPos(scip, cons, i) );
4015  }
4016  else
4017  consdata->vals[i] = newval;
4018  }
4019 
4020  /* scale the sides */
4021  if( scalar < 0.0 )
4022  {
4023  SCIP_Real lhs;
4024 
4025  lhs = consdata->lhs;
4026  consdata->lhs = -consdata->rhs;
4027  consdata->rhs = -lhs;
4028  }
4029  absscalar = REALABS(scalar);
4030  if( !SCIPisInfinity(scip, -consdata->lhs) )
4031  {
4032  newval = absscalar * consdata->lhs;
4033 
4034  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4035  * flooring down our new value
4036  */
4037  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4038  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4039  else
4040  consdata->lhs = newval;
4041  }
4042  if( !SCIPisInfinity(scip, consdata->rhs) )
4043  {
4044  newval = absscalar * consdata->rhs;
4045 
4046  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4047  * our new value
4048  */
4049  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4050  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4051  else
4052  consdata->rhs = newval;
4053  }
4054 
4055  consdataInvalidateActivities(consdata);
4056  consdata->cliquesadded = FALSE;
4057  consdata->implsadded = FALSE;
4058 
4059  return SCIP_OKAY;
4060 }
4061 
4062 /* perform deletion of variables in all constraints of the constraint handler */
4063 static
4065  SCIP* scip, /**< SCIP data structure */
4066  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4067  SCIP_CONS** conss, /**< array of constraints */
4068  int nconss /**< number of constraints */
4069  )
4070 {
4071  SCIP_CONSDATA* consdata;
4072  int i;
4073  int v;
4074 
4075  assert(scip != NULL);
4076  assert(conshdlr != NULL);
4077  assert(conss != NULL);
4078  assert(nconss >= 0);
4079  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4080 
4081  /* iterate over all constraints */
4082  for( i = 0; i < nconss; i++ )
4083  {
4084  consdata = SCIPconsGetData(conss[i]);
4085 
4086  /* constraint is marked, that some of its variables were deleted */
4087  if( consdata->varsdeleted )
4088  {
4089  /* iterate over all variables of the constraint and delete them from the constraint */
4090  for( v = consdata->nvars - 1; v >= 0; --v )
4091  {
4092  if( SCIPvarIsDeleted(consdata->vars[v]) )
4093  {
4094  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4095  }
4096  }
4097  consdata->varsdeleted = FALSE;
4098  }
4099  }
4100 
4101  return SCIP_OKAY;
4102 }
4103 
4104 
4105 /** normalizes a linear constraint with the following rules:
4106  * - if all coefficients have them same absolute value, change them to (-)1.0
4107  * - multiplication with +1 or -1:
4108  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4109  * if the current rule doesn't determine the sign):
4110  * 1. the right hand side must not be negative
4111  * 2. the right hand side must not be infinite
4112  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4113  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4114  * 5. multiply with +1
4115  * - rationals to integrals
4116  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4117  * by the smallest common multiple of all denominators to get integral coefficients.
4118  * Forbid large denominators due to numerical stability.
4119  * - division by greatest common divisor
4120  * If all coefficients are integral, divide them by the greatest common divisor.
4121  */
4122 static
4124  SCIP* scip, /**< SCIP data structure */
4125  SCIP_CONS* cons /**< linear constraint to normalize */
4126  )
4127 {
4128  SCIP_CONSDATA* consdata;
4129  SCIP_VAR** vars;
4130  SCIP_Real* vals;
4131  SCIP_Longint scm;
4132  SCIP_Longint nominator;
4133  SCIP_Longint denominator;
4134  SCIP_Longint gcd;
4135  SCIP_Longint maxmult;
4136  SCIP_Real epsilon;
4137  SCIP_Real feastol;
4138  SCIP_Real maxabsval;
4139  SCIP_Real minabsval;
4140  SCIP_Bool success;
4141  SCIP_Bool onlyintegral;
4142  int nvars;
4143  int mult;
4144  int nposcoeffs;
4145  int nnegcoeffs;
4146  int i;
4147  int v;
4148 
4149  assert(scip != NULL);
4150  assert(cons != NULL);
4151 
4152  /* we must not change a modifiable constraint in any way */
4153  if( SCIPconsIsModifiable(cons) )
4154  return SCIP_OKAY;
4155 
4156  /* get constraint data */
4157  consdata = SCIPconsGetData(cons);
4158  assert(consdata != NULL);
4159 
4160  /* check, if the constraint is already normalized */
4161  if( consdata->normalized )
4162  return SCIP_OKAY;
4163 
4164  /* get coefficient arrays */
4165  vals = consdata->vals;
4166  nvars = consdata->nvars;
4167  vars = consdata->vars;
4168  assert(nvars == 0 || vars != NULL);
4169  assert(nvars == 0 || vals != NULL);
4170 
4171  if( nvars == 0 )
4172  {
4173  consdata->normalized = TRUE;
4174  return SCIP_OKAY;
4175  }
4176 
4177  assert(vars != NULL);
4178  assert(vals != NULL);
4179 
4180  /* get maximal and minimal absolute coefficient */
4181  maxabsval = consdataGetMaxAbsval(consdata);
4182  minabsval = consdataGetMinAbsval(consdata);
4183 
4184  /* return if scaling by maxval will eliminate coefficients */
4185  if( SCIPisZero(scip, minabsval/maxabsval) )
4186  return SCIP_OKAY;
4187 
4188  /* check if all coefficients are in absolute value equal, and not 1.0 */
4189  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4190  {
4191  SCIP_Bool abscoefsequ;
4192 
4193  abscoefsequ = TRUE;
4194 
4195  for( v = nvars - 1; v >= 0; --v )
4196  {
4197  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4198  {
4199  abscoefsequ = FALSE;
4200  break;
4201  }
4202  }
4203 
4204  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4205  if( abscoefsequ )
4206  {
4207  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficents are in absolute value the same\n", maxabsval);
4208  SCIPdebugPrintCons(scip, cons, NULL);
4209  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4210 
4211  if( consdata->validmaxabsval )
4212  {
4213  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4214  consdata->maxabsval = 1.0;
4215  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4216  consdata->minabsval = 1.0;
4217 
4218  maxabsval = 1.0;
4219  }
4220  else
4221  {
4222  /* get maximal absolute coefficient */
4223  maxabsval = consdataGetMaxAbsval(consdata);
4224  }
4225 
4226  /* get new consdata information, because scalecons() might have deleted variables */
4227  vals = consdata->vals;
4228  nvars = consdata->nvars;
4229  vars = consdata->vars;
4230 
4231  assert(nvars == 0 || vars != NULL);
4232  assert(nvars == 0 || vals != NULL);
4233  }
4234  }
4235 
4236  /* nvars might have changed */
4237  if( nvars == 0 )
4238  {
4239  consdata->normalized = TRUE;
4240  return SCIP_OKAY;
4241  }
4242 
4243  assert(vars != NULL);
4244  assert(vals != NULL);
4245 
4246  /* calculate the maximal multiplier for common divisor calculation:
4247  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4248  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4249  * additionally, we don't want to scale the constraint if this would lead to too
4250  * large coefficients
4251  */
4252  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4253  feastol = SCIPfeastol(scip);
4254  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4255  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
4256 
4257  if( !consdata->hasnonbinvalid )
4258  consdataCheckNonbinvar(consdata);
4259 
4260  /* if all variables are of integral type we will allow a greater multiplier */
4261  if( !consdata->hascontvar )
4262  {
4263  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
4264  {
4265  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4266  }
4267  }
4268  else
4269  {
4270  SCIP_Bool foundcont;
4271 
4272  foundcont = FALSE;
4273 
4274  for( v = nvars - 1; v >= 0; --v )
4275  {
4276  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4277  {
4278  foundcont = TRUE;
4279  break;
4280  }
4281  }
4282 
4283  if( !foundcont )
4284  {
4285  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4286  }
4287  }
4288 
4289  /*
4290  * multiplication with +1 or -1
4291  */
4292  mult = 0;
4293 
4294  /* 1. the right hand side must not be negative */
4295  if( SCIPisPositive(scip, consdata->lhs) )
4296  mult = +1;
4297  else if( SCIPisNegative(scip, consdata->rhs) )
4298  mult = -1;
4299 
4300  if( mult == 0 )
4301  {
4302  /* 2. the right hand side must not be infinite */
4303  if( SCIPisInfinity(scip, -consdata->lhs) )
4304  mult = +1;
4305  else if( SCIPisInfinity(scip, consdata->rhs) )
4306  mult = -1;
4307  }
4308 
4309  if( mult == 0 )
4310  {
4311  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4312  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4313  mult = +1;
4314  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4315  mult = -1;
4316  }
4317 
4318  if( mult == 0 )
4319  {
4320  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4321  nposcoeffs = 0;
4322  nnegcoeffs = 0;
4323  for( i = 0; i < nvars; ++i )
4324  {
4325  if( vals[i] > 0.0 )
4326  nposcoeffs++;
4327  else
4328  nnegcoeffs++;
4329  }
4330  if( nposcoeffs > nnegcoeffs )
4331  mult = +1;
4332  else if( nposcoeffs < nnegcoeffs )
4333  mult = -1;
4334  }
4335 
4336  if( mult == 0 )
4337  {
4338  /* 5. multiply with +1 */
4339  mult = +1;
4340  }
4341 
4342  assert(mult == +1 || mult == -1);
4343  if( mult == -1 )
4344  {
4345  /* scale the constraint with -1 */
4346  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4347  SCIPdebugPrintCons(scip, cons, NULL);
4348  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4349 
4350  /* scalecons() can delete variables, but scaling with -1 should not do that */
4351  assert(nvars == consdata->nvars);
4352  }
4353 
4354  /*
4355  * rationals to integrals
4356  *
4357  * @todo try scaling only on behalf of non-continuous variables
4358  */
4359  success = TRUE;
4360  scm = 1;
4361  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4362  {
4363  if( !SCIPisIntegral(scip, vals[i]) )
4364  {
4365  /* epsilon has been slightly decreased above - to be on the safe side */
4366  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4367  if( success )
4368  scm = SCIPcalcSmaComMul(scm, denominator);
4369  }
4370  }
4371  assert(scm >= 1);
4372 
4373  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4374  * their greatest common divisor
4375  */
4376  onlyintegral = TRUE;
4377  if( scm == 1 )
4378  {
4379  for( i = nvars - 1; i >= 0; --i )
4380  {
4381  if( !SCIPisIntegral(scip, vals[i]) )
4382  {
4383  onlyintegral = FALSE;
4384  break;
4385  }
4386  }
4387  }
4388 
4389  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4390  if( success && scm != 1 )
4391  {
4392  /* scale the constraint with the smallest common multiple of all denominators */
4393  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4394  SCIPdebugPrintCons(scip, cons, NULL);
4395  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4396 
4397  if( consdata->validmaxabsval )
4398  {
4399  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4400  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4401  {
4402  consdata->validmaxabsval = FALSE;
4403  consdata->maxabsval = SCIP_INVALID;
4404  consdataCalcMaxAbsval(consdata);
4405  }
4406  }
4407 
4408  if( consdata->validminabsval )
4409  {
4410  consdata->minabsval *= REALABS((SCIP_Real)scm);
4411  if( !SCIPisIntegral(scip, consdata->minabsval) )
4412  {
4413  consdata->validminabsval = FALSE;
4414  consdata->minabsval = SCIP_INVALID;
4415  consdataCalcMinAbsval(consdata);
4416  }
4417  }
4418 
4419  /* get new consdata information, because scalecons() might have deleted variables */
4420  vals = consdata->vals;
4421  nvars = consdata->nvars;
4422  assert(nvars == 0 || vals != NULL);
4423  }
4424 
4425  /*
4426  * division by greatest common divisor
4427  */
4428  if( success && nvars >= 1 )
4429  {
4430  /* all coefficients are integral: divide them by their greatest common divisor */
4431  assert(SCIPisIntegral(scip, vals[0]));
4432 
4433  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4434  for( i = 1; i < nvars && gcd > 1; ++i )
4435  {
4436  assert(SCIPisIntegral(scip, vals[i]));
4437  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4438  }
4439 
4440  if( gcd > 1 )
4441  {
4442  /* divide the constraint by the greatest common divisor of the coefficients */
4443  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4444  SCIPdebugPrintCons(scip, cons, NULL);
4445  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4446 
4447  if( consdata->validmaxabsval )
4448  {
4449  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4450  }
4451  if( consdata->validminabsval )
4452  {
4453  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4454  }
4455  }
4456  }
4457 
4458  /* mark constraint to be normalized */
4459  consdata->normalized = TRUE;
4460 
4461  SCIPdebugMsg(scip, "normalized constraint:\n");
4462  SCIPdebugPrintCons(scip, cons, NULL);
4463 
4464  return SCIP_OKAY;
4465 }
4466 
4467 /** replaces multiple occurrences of a variable by a single coefficient */
4468 static
4470  SCIP* scip, /**< SCIP data structure */
4471  SCIP_CONS* cons /**< linear constraint */
4472  )
4473 {
4474  SCIP_CONSDATA* consdata;
4475  SCIP_VAR* var;
4476  SCIP_Real valsum;
4477  int v;
4478 
4479  assert(scip != NULL);
4480  assert(cons != NULL);
4481 
4482  consdata = SCIPconsGetData(cons);
4483  assert(consdata != NULL);
4484 
4485  if( consdata->merged )
4486  return SCIP_OKAY;
4487 
4488  /* sort the constraint */
4489  SCIP_CALL( consdataSort(scip, consdata) );
4490 
4491  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4492  * backward direction is necessary, since delCoefPos() modifies the given position and
4493  * the subsequent ones
4494  */
4495  v = consdata->nvars-1;
4496  while( v >= 1 )
4497  {
4498  var = consdata->vars[v];
4499  if( consdata->vars[v-1] == var )
4500  {
4501  valsum = consdata->vals[v];
4502  do
4503  {
4504  SCIP_CALL( delCoefPos(scip, cons, v) );
4505  --v;
4506  valsum += consdata->vals[v];
4507  }
4508  while( v >= 1 && consdata->vars[v-1] == var );
4509 
4510  /* modify the last existing occurrence of the variable */
4511  assert(consdata->vars[v] == var);
4512  if( SCIPisZero(scip, valsum) )
4513  {
4514  SCIP_CALL( delCoefPos(scip, cons, v) );
4515 
4516  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4517  * delta needs to be recalculated on the next real propagation
4518  */
4519  if( consdata->maxactdeltavar == var )
4520  {
4521  consdata->maxactdelta = SCIP_INVALID;
4522  consdata->maxactdeltavar = NULL;
4523  }
4524  }
4525  else
4526  {
4527  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4528  }
4529  }
4530  --v;
4531  }
4532 
4533  consdata->merged = TRUE;
4534 
4535  return SCIP_OKAY;
4536 }
4537 
4538 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4539 static
4541  SCIP* scip, /**< SCIP data structure */
4542  SCIP_CONS* cons, /**< linear constraint */
4543  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4544  * information is not needed; in this case, we apply all fixings
4545  * instead of stopping after the first infeasible one */
4546  )
4547 {
4548  SCIP_CONSDATA* consdata;
4549  SCIP_VAR* var;
4550  SCIP_VAR** aggrvars;
4551  SCIP_Real val;
4552  SCIP_Real* aggrscalars;
4553  SCIP_Real fixedval;
4554  SCIP_Real aggrconst;
4555  int v;
4556  int naggrvars;
4557  int i;
4558 
4559  assert(scip != NULL);
4560  assert(cons != NULL);
4561 
4562  if( infeasible != NULL )
4563  *infeasible = FALSE;
4564 
4565  consdata = SCIPconsGetData(cons);
4566  assert(consdata != NULL);
4567 
4568  if( !consdata->removedfixings )
4569  {
4570  SCIP_Real lhssubtrahend;
4571  SCIP_Real rhssubtrahend;
4572 
4573  lhssubtrahend = 0.0;
4574  rhssubtrahend = 0.0;
4575 
4576  SCIPdebugMsg(scip, "applying fixings:\n");
4577  SCIPdebugPrintCons(scip, cons, NULL);
4578 
4579  v = 0;
4580  while( v < consdata->nvars )
4581  {
4582  var = consdata->vars[v];
4583  val = consdata->vals[v];
4584  assert(SCIPvarIsTransformed(var));
4585 
4586  switch( SCIPvarGetStatus(var) )
4587  {
4589  SCIPerrorMessage("original variable in transformed linear constraint\n");
4590  return SCIP_INVALIDDATA;
4591 
4592  case SCIP_VARSTATUS_LOOSE:
4593  case SCIP_VARSTATUS_COLUMN:
4594  ++v;
4595  break;
4596 
4597  case SCIP_VARSTATUS_FIXED:
4598  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4599  fixedval = SCIPvarGetLbGlobal(var);
4600  if( !SCIPisInfinity(scip, -consdata->lhs) )
4601  {
4602  if( SCIPisInfinity(scip, ABS(fixedval)) )
4603  {
4604  if( val * fixedval > 0.0 )
4605  {
4606  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4607  }
4608  else
4609  {
4610  if( infeasible != NULL )
4611  {
4612  /* if lhs gets infinity it means that the problem is infeasible */
4613  *infeasible = TRUE;
4614  return SCIP_OKAY;
4615  }
4616  else
4617  {
4618  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4619  }
4620  }
4621  }
4622  else
4623  lhssubtrahend += val * fixedval;
4624  }
4625  if( !SCIPisInfinity(scip, consdata->rhs) )
4626  {
4627  if( SCIPisInfinity(scip, ABS(fixedval)) )
4628  {
4629  if( val * fixedval > 0.0 )
4630  {
4631  if( infeasible != NULL )
4632  {
4633  /* if rhs gets -infinity it means that the problem is infeasible */
4634  *infeasible = TRUE;
4635  return SCIP_OKAY;
4636  }
4637  else
4638  {
4639  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4640  }
4641  }
4642  else
4643  {
4644  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4645  }
4646  }
4647  else
4648  rhssubtrahend += val * fixedval;
4649  }
4650  SCIP_CALL( delCoefPos(scip, cons, v) );
4651  break;
4652 
4654  {
4655  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4656  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4657  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4658 
4659  assert(activevar != NULL);
4660  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4661  assert(activevar != NULL);
4662 
4663  if( !SCIPisZero(scip, activescalar) )
4664  {
4665  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4666  }
4667 
4668  if( !SCIPisZero(scip, activeconstant) )
4669  {
4670  if( !SCIPisInfinity(scip, -consdata->lhs) )
4671  lhssubtrahend += activeconstant;
4672  if( !SCIPisInfinity(scip, consdata->rhs) )
4673  rhssubtrahend += activeconstant;
4674  }
4675 
4676  SCIP_CALL( delCoefPos(scip, cons, v) );
4677  break;
4678  }
4681  naggrvars = SCIPvarGetMultaggrNVars(var);
4682  aggrvars = SCIPvarGetMultaggrVars(var);
4683  aggrscalars = SCIPvarGetMultaggrScalars(var);
4684  for( i = 0; i < naggrvars; ++i )
4685  {
4686  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4687  }
4688  aggrconst = SCIPvarGetMultaggrConstant(var);
4689 
4690  if( !SCIPisInfinity(scip, -consdata->lhs) )
4691  lhssubtrahend += val * aggrconst;
4692  if( !SCIPisInfinity(scip, consdata->rhs) )
4693  rhssubtrahend += val * aggrconst;
4694 
4695  SCIP_CALL( delCoefPos(scip, cons, v) );
4696  break;
4697 
4699  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4700  aggrconst = SCIPvarGetNegationConstant(var);
4701 
4702  if( !SCIPisInfinity(scip, -consdata->lhs) )
4703  lhssubtrahend += val * aggrconst;
4704  if( !SCIPisInfinity(scip, consdata->rhs) )
4705  rhssubtrahend += val * aggrconst;
4706 
4707  SCIP_CALL( delCoefPos(scip, cons, v) );
4708  break;
4709 
4710  default:
4711  SCIPerrorMessage("unknown variable status\n");
4712  SCIPABORT();
4713  return SCIP_INVALIDDATA; /*lint !e527*/
4714  }
4715  }
4716 
4717  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4718  {
4719  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4720  * causing wrong fixings of other variables --> better use a real zero here;
4721  * for small numbers, polishing the difference might lead to wrong results -->
4722  * better use the exact difference in this case
4723  */
4724  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4725  {
4726  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4727  }
4728  else
4729  {
4730  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4731  }
4732  }
4733  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4734  {
4735 
4736  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4737  * causing wrong fixings of other variables --> better use a real zero here;
4738  * for small numbers, polishing the difference might lead to wrong results -->
4739  * better use the exact difference in this case
4740  */
4741  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4742  {
4743  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4744  }
4745  else
4746  {
4747  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4748  }
4749  }
4750 
4751  consdata->removedfixings = TRUE;
4752 
4753  SCIPdebugMsg(scip, "after fixings:\n");
4754  SCIPdebugPrintCons(scip, cons, NULL);
4755 
4756  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4757  * to clean up the constraint
4758  */
4759  SCIP_CALL( mergeMultiples(scip, cons) );
4760 
4761  SCIPdebugMsg(scip, "after merging:\n");
4762  SCIPdebugPrintCons(scip, cons, NULL);
4763  }
4764  assert(consdata->removedfixings);
4765 
4766 #ifndef NDEBUG
4767  /* check, if all fixings are applied */
4768  for( v = 0; v < consdata->nvars; ++v )
4769  assert(SCIPvarIsActive(consdata->vars[v]));
4770 #endif
4771 
4772  return SCIP_OKAY;
4773 }
4774 
4775 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4776  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4777  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4778  * conflict detecting constraint by using NULL as inferred variable
4779  */
4780 static
4782  SCIP* scip, /**< SCIP data structure */
4783  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4784  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4785  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4786  int inferpos, /**< position of the inferred variable in the vars array */
4787  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4788  )
4789 {
4790  SCIP_CONSDATA* consdata;
4791  SCIP_VAR** vars;
4792  SCIP_Real* vals;
4793  int nvars;
4794  int i;
4795 
4796  assert(scip != NULL);
4797  assert(cons != NULL);
4799  consdata = SCIPconsGetData(cons);
4800 
4801  assert(consdata != NULL);
4802 
4803  vars = consdata->vars;
4804  vals = consdata->vals;
4805  nvars = consdata->nvars;
4806 
4807  assert(vars != NULL || nvars == 0);
4808  assert(vals != NULL || nvars == 0);
4809 
4810  assert(-1 <= inferpos && inferpos < nvars);
4811  assert((infervar == NULL) == (inferpos == -1));
4812  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4813 
4814  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4815  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4816  * - if the right hand side is the reason, the minimal residual activity is responsible
4817  * - if the left hand side is the reason, the maximal residual activity is responsible
4818  */
4819 
4820  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4821  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4822  {
4823  SCIP_Real minresactivity;
4824  SCIP_Real maxresactivity;
4825  SCIP_Bool minisrelax;
4826  SCIP_Bool maxisrelax;
4827  SCIP_Bool isminsettoinfinity;
4828  SCIP_Bool ismaxsettoinfinity;
4829 
4830  minresactivity = -SCIPinfinity(scip);
4831  maxresactivity = SCIPinfinity(scip);
4832 
4833  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4834  if( infervar != NULL )
4835  {
4836  assert(vals != NULL); /* for flexelint */
4837  if( reasonisrhs )
4838  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4839  &minisrelax, NULL, &isminsettoinfinity, NULL);
4840  else
4841  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4842  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4843  }
4844  else
4845  {
4846  if( reasonisrhs )
4847  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4848  &minisrelax, NULL, &isminsettoinfinity, NULL);
4849  else
4850  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4851  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4852  }
4853 
4854  /* we can only do something clever, if the residual activity is finite and not relaxed */
4855  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4856  {
4857  SCIP_Real rescap;
4858  SCIP_Bool resactisinf;
4859 
4860  resactisinf = FALSE;
4861 
4862  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4863  * than its inferred bound
4864  */
4865  if( infervar != NULL )
4866  {
4867  assert(vals != NULL); /* for flexelint */
4868 
4869  if( reasonisrhs )
4870  {
4871  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4872  {
4873  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4874  if( SCIPisInfinity(scip, -minresactivity) )
4875  resactisinf = TRUE;
4876  }
4877  rescap = consdata->rhs - minresactivity;
4878  }
4879  else
4880  {
4881  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4882  {
4883  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4884  if( SCIPisInfinity(scip, maxresactivity) )
4885  resactisinf = TRUE;
4886  }
4887  rescap = consdata->lhs - maxresactivity;
4888  }
4889 
4890  if( reasonisrhs == (vals[inferpos] > 0.0) )
4891  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4892  else
4893  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4894  }
4895  else
4896  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4897 
4898  if( !resactisinf )
4899  {
4900  /* now add bounds as reasons until the residual capacity is exceeded */
4901  for( i = 0; i < nvars; ++i )
4902  {
4903  assert( vars != NULL && vals != NULL ); /* for lint */
4904 
4905  /* zero coefficients and the infered variable can be ignored */
4906  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4907  continue;
4908 
4909  /* check if the residual capacity is exceeded */
4910  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4911  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4912  break;
4913 
4914  /* update the residual capacity due to the local bound of this variable */
4915  if( reasonisrhs == (vals[i] > 0.0) )
4916  {
4917  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4918  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4919  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4920  }
4921  else
4922  {
4923  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4924  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4925  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4926  }
4927  }
4928  return SCIP_OKAY;
4929  }
4930  }
4931  }
4932 
4933  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4934  for( i = 0; i < nvars; ++i )
4935  {
4936  assert(vars != NULL); /* for flexelint */
4937  assert(vals != NULL); /* for flexelint */
4938 
4939  /* zero coefficients and the infered variable can be ignored */
4940  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4941  continue;
4942 
4943  if( reasonisrhs == (vals[i] > 0.0) )
4944  {
4945  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4946  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4947  }
4948  else
4949  {
4950  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4951  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4952  }
4953  }
4954 
4955  return SCIP_OKAY;
4956 }
4957 
4958 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4959  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4960  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4961  */
4962 static
4964  SCIP* scip, /**< SCIP data structure */
4965  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4966  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4967  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4968  int inferpos /**< position of the inferred variable in the vars array, or -1 */
4969  )
4970 {
4971  SCIP_CONSDATA* consdata;
4972  SCIP_VAR** vars;
4973  int nvars;
4974  int v;
4975 
4976  assert(scip != NULL);
4977  assert(cons != NULL);
4978 
4979  consdata = SCIPconsGetData(cons);
4980  assert(consdata != NULL);
4981  vars = consdata->vars;
4982  nvars = consdata->nvars;
4983  assert(vars != NULL || nvars == 0);
4984  assert(-1 <= inferpos && inferpos < nvars);
4985  assert((infervar == NULL) == (inferpos == -1));
4986  assert(inferpos == -1 || vars != NULL);
4987  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4988 
4989  /* collect all fixed variables */
4990  for( v = nvars - 1; v >= 0; --v )
4991  {
4992  assert(vars != NULL); /* for flexelint */
4993 
4994  /* need to add old bounds before propagation of inferrence variable */
4995  if( vars[v] == infervar )
4996  {
4997  assert(vars[v] != NULL);
4998 
4999  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5000  {
5001  /* @todo get boundchange index before this last boundchange and correct the index */
5002  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5003  }
5004 
5005  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5006  {
5007  /* @todo get boundchange index before this last boundchange and correct the index */
5008  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5009  }
5010 
5011  continue;
5012  }
5013 
5014  /* check for fixed variables */
5015  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5016  {
5017  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5018  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5019  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5020  }
5021  }
5022 
5023  return SCIP_OKAY;
5024 }
5025 
5026 /** add reasoning variables to conflict candidate queue which led to the conflict */
5027 static
5029  SCIP* scip, /**< SCIP data structure */
5030  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5031  int nvars, /**< number of variables reasoning the infeasibility */
5032  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5033  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5034  )
5035 {
5036  int v;
5037 
5038  assert(scip != NULL);
5039 
5040  /* collect all variables for which the local bounds differ from their global bounds */
5041  for( v = nvars - 1; v >= 0; --v )
5042  {
5043  assert(vars != NULL);
5044 
5045  /* check for local bound changes variables */
5046  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5047  {
5048  /* add conflict bound */
5049  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5050  }
5051 
5052  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5053  {
5054  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5055  }
5056  }
5057 
5058  if( var != NULL )
5059  {
5060  if( bound < SCIPvarGetLbLocal(var) )
5061  {
5062  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5063  }
5064 
5065  if( bound > SCIPvarGetUbLocal(var) )
5066  {
5067  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5068  }
5069  }
5070 
5071  return SCIP_OKAY;
5072 }
5073 
5074 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5075  * propagation rule (see propagateCons()):
5076  * (1) activity residuals of all other variables tighten bounds of single variable
5077  */
5078 static
5080  SCIP* scip, /**< SCIP data structure */
5081  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5082  SCIP_VAR* infervar, /**< variable that was deduced */
5083  INFERINFO inferinfo, /**< inference information */
5084  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5085  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5086  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5087  )
5088 {
5089  SCIP_CONSDATA* consdata;
5090  SCIP_VAR** vars;
5091 #ifndef NDEBUG
5092  SCIP_Real* vals;
5093 #endif
5094  int nvars;
5095  int inferpos;
5097  assert(scip != NULL);
5098  assert(cons != NULL);
5099  assert(result != NULL);
5100 
5101  consdata = SCIPconsGetData(cons);
5102  assert(consdata != NULL);
5103  vars = consdata->vars;
5104  nvars = consdata->nvars;
5105 #ifndef NDEBUG
5106  vals = consdata->vals;
5107  assert(vars != NULL);
5108  assert(vals != NULL);
5109 #endif
5110 
5111  /* get the position of the inferred variable in the vars array */
5112  inferpos = inferInfoGetPos(inferinfo);
5113  if( inferpos >= nvars || vars[inferpos] != infervar )
5114  {
5115  /* find inference variable in constraint */
5116  /**@todo use a binary search here; the variables can be sorted by variable index */
5117  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5118  {}
5119  }
5120  assert(inferpos < nvars);
5121  assert(vars[inferpos] == infervar);
5122  assert(!SCIPisZero(scip, vals[inferpos]));
5123 
5124  switch( inferInfoGetProprule(inferinfo) )
5125  {
5126  case PROPRULE_1_RHS:
5127  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5128  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5129  * domain in order to not exceed the right hand side of the inequality
5130  */
5131  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5132  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5133  *result = SCIP_SUCCESS;
5134  break;
5135 
5136  case PROPRULE_1_LHS:
5137  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5138  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5139  * domain in order to not fall below the left hand side of the inequality
5140  */
5141  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5142  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5143  *result = SCIP_SUCCESS;
5144  break;
5145 
5146  case PROPRULE_1_RANGEDROW:
5147  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5148  * the given inference variable to their bounds in this given ranged row
5149  */
5150 
5151  /* check that we really have a ranged row here */
5152  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5153  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5154  *result = SCIP_SUCCESS;
5155  break;
5156 
5157  case PROPRULE_INVALID:
5158  default:
5159  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5160  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5161  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5162  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5163  SCIPinfoMessage(scip, NULL, ";\n");
5164  return SCIP_INVALIDDATA;
5165  }
5166 
5167  return SCIP_OKAY;
5168 }
5169 
5170 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5171 static
5173  SCIP* scip, /**< SCIP data structure */
5174  SCIP_CONS* cons, /**< conflict detecting constraint */
5175  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5176  )
5177 {
5178  /* conflict analysis can only be applied in solving stage and if it is turned on */
5180  return SCIP_OKAY;
5181 
5182  /* initialize conflict analysis */
5184 
5185  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5186  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5187 
5188  /* analyze the conflict */
5189  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5190 
5191  return SCIP_OKAY;
5192 }
5193 
5194 /** check if there is any hope of tightening some bounds */
5195 static
5197  SCIP* scip, /**< SCIP data structure */
5198  SCIP_CONS* cons /**< linear constraint */
5199  )
5200 {
5201  SCIP_CONSDATA* consdata;
5202  int infcountmin;
5203  int infcountmax;
5204 
5205  consdata = SCIPconsGetData(cons);
5206  assert(consdata != NULL);
5207 
5208  infcountmin = consdata->minactivityneginf
5209  + consdata->minactivityposinf
5210  + consdata->minactivityneghuge
5211  + consdata->minactivityposhuge;
5212  infcountmax = consdata->maxactivityneginf
5213  + consdata->maxactivityposinf
5214  + consdata->maxactivityneghuge
5215  + consdata->maxactivityposhuge;
5216 
5217  if( infcountmin > 1 && infcountmax > 1 )
5218  return FALSE;
5219 
5220  return TRUE;
5221 }
5222 
5223 /** tighten upper bound */
5224 static
5226  SCIP* scip, /**< SCIP data structure */
5227  SCIP_CONS* cons, /**< linear constraint */
5228  int pos, /**< variable position */
5229  PROPRULE proprule, /**< propagation rule that deduced the value */
5230  SCIP_Real newub, /**< new upper bound */
5231  SCIP_Real oldub, /**< old upper bound */
5232  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5233  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5234  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5235  )
5236 {
5237  SCIP_CONSDATA* consdata;
5238  SCIP_VAR* var;
5239  SCIP_Real lb;
5240  SCIP_Bool infeasible;
5241  SCIP_Bool tightened;
5243  assert(cons != NULL);
5244  assert(!SCIPisInfinity(scip, newub));
5245 
5246  consdata = SCIPconsGetData(cons);
5247  assert(consdata != NULL);
5248  var = consdata->vars[pos];
5249  assert(var != NULL);
5250 
5251  lb = SCIPvarGetLbLocal(var);
5252  newub = SCIPadjustedVarUb(scip, var, newub);
5253 
5254  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5255  {
5256  SCIP_VARTYPE vartype;
5257 
5258  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5259  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5260 
5261  vartype = SCIPvarGetType(var);
5262 
5263  /* tighten upper bound */
5264  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5265 
5266  if( infeasible )
5267  {
5268  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5269  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5270 
5271  /* analyze conflict */
5272  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5273 
5274  *cutoff = TRUE;
5275  }
5276  else if( tightened )
5277  {
5278  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5279  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5280  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5281 
5282  (*nchgbds)++;
5283 
5284  /* if variable type was changed we might be able to upgrade the constraint */
5285  if( vartype != SCIPvarGetType(var) )
5286  consdata->upgradetried = FALSE;
5287  }
5288  }
5289  return SCIP_OKAY;
5290 }
5291 
5292 /** tighten lower bound */
5293 static
5295  SCIP* scip, /**< SCIP data structure */
5296  SCIP_CONS* cons, /**< linear constraint */
5297  int pos, /**< variable position */
5298  PROPRULE proprule, /**< propagation rule that deduced the value */
5299  SCIP_Real newlb, /**< new lower bound */
5300  SCIP_Real oldlb, /**< old lower bound */
5301  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5302  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5303  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5304  )
5305 {
5306  SCIP_CONSDATA* consdata;
5307  SCIP_VAR* var;
5308  SCIP_Real ub;
5309  SCIP_Bool infeasible;
5310  SCIP_Bool tightened;
5312  assert(cons != NULL);
5313  assert(!SCIPisInfinity(scip, newlb));
5314 
5315  consdata = SCIPconsGetData(cons);
5316  assert(consdata != NULL);
5317  var = consdata->vars[pos];
5318  assert(var != NULL);
5319 
5320  ub = SCIPvarGetUbLocal(var);
5321  newlb = SCIPadjustedVarLb(scip, var, newlb);
5322 
5323  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5324  {
5325  SCIP_VARTYPE vartype;
5326 
5327  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5328  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5329 
5330  vartype = SCIPvarGetType(var);
5331 
5332  /* tighten lower bound */
5333  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5334 
5335  if( infeasible )
5336  {
5337  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5338  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5339 
5340  /* analyze conflict */
5341  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5342 
5343  *cutoff = TRUE;
5344  }
5345  else if( tightened )
5346  {
5347  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5348  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5349  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5350 
5351  (*nchgbds)++;
5352 
5353  /* if variable type was changed we might be able to upgrade the constraint */
5354  if( vartype != SCIPvarGetType(var) )
5355  consdata->upgradetried = FALSE;
5356  }
5357  }
5358  return SCIP_OKAY;
5359 }
5360 
5361 /** tightens bounds of a single variable due to activity bounds (easy case) */
5362 static
5364  SCIP* scip, /**< SCIP data structure */
5365  SCIP_CONS* cons, /**< linear constraint */
5366  int pos, /**< position of the variable in the vars array */
5367  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5368  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5369  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5370  )
5371 {
5372  SCIP_CONSDATA* consdata;
5373  SCIP_VAR* var;
5374  SCIP_Real val;
5375  SCIP_Real lb;
5376  SCIP_Real ub;
5377  SCIP_Real lhs;
5378  SCIP_Real rhs;
5379 
5380  assert(scip != NULL);
5381  assert(cons != NULL);
5382  assert(cutoff != NULL);
5383  assert(nchgbds != NULL);
5384 
5385  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5386  if( SCIPconsIsModifiable(cons) )
5387  return SCIP_OKAY;
5388 
5389  consdata = SCIPconsGetData(cons);
5390  assert(consdata != NULL);
5391  assert(0 <= pos && pos < consdata->nvars);
5392 
5393  *cutoff = FALSE;
5394 
5395  var = consdata->vars[pos];
5396  assert(var != NULL);
5397 
5398  /* we cannot tighten bounds of multi-aggregated variables */
5400  return SCIP_OKAY;
5401 
5402  val = consdata->vals[pos];
5403  lhs = consdata->lhs;
5404  rhs = consdata->rhs;
5405  assert(!SCIPisZero(scip, val));
5406  assert(!SCIPisInfinity(scip, lhs));
5407  assert(!SCIPisInfinity(scip, -rhs));
5408 
5409  lb = SCIPvarGetLbLocal(var);
5410  ub = SCIPvarGetUbLocal(var);
5411  assert(SCIPisLE(scip, lb, ub));
5412 
5413  /* recompute activities if needed */
5414  if( !consdata->validactivities )
5415  consdataCalcActivities(scip, consdata);
5416  assert(consdata->validactivities);
5417  if( !consdata->validminact )
5418  consdataRecomputeMinactivity(scip, consdata);
5419  assert(consdata->validminact);
5420  if( !consdata->validmaxact )
5421  consdataRecomputeMaxactivity(scip, consdata);
5422  assert(consdata->validmaxact);
5423 
5424  if( val > 0.0 )
5425  {
5426  /* check, if we can tighten the variable's upper bound */
5427  if( !SCIPisInfinity(scip, rhs) )
5428  {
5429  SCIP_Real slack;
5430  SCIP_Real alpha;
5431 
5432  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5433  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5434  {
5435  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5436  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5437 
5438  *cutoff = TRUE;
5439  return SCIP_OKAY;
5440  }
5441 
5442  slack = rhs - consdata->minactivity;
5443 
5444  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5445  * it to zero
5446  */
5447  if( !SCIPisPositive(scip, slack) )
5448  slack = 0.0;
5449 
5450  alpha = val * (ub - lb);
5451  assert(!SCIPisNegative(scip, alpha));
5452 
5453  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5454  {
5455  SCIP_Real newub;
5456 
5457  /* compute new upper bound */
5458  newub = lb + (slack / val);
5459 
5460  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5461 
5462  if( *cutoff )
5463  {
5464  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5465  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5466 
5467  return SCIP_OKAY;
5468  }
5469 
5470  /* collect the new upper bound which is needed for the lower bound computation */
5471  ub = SCIPvarGetUbLocal(var);
5472  }
5473  }
5474 
5475  /* check, if we can tighten the variable's lower bound */
5476  if( !SCIPisInfinity(scip, -lhs) )
5477  {
5478  SCIP_Real slack;
5479  SCIP_Real alpha;
5480 
5481  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5482  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5483  {
5484  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5485  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5486 
5487  *cutoff = TRUE;
5488  return SCIP_OKAY;
5489  }
5490 
5491  slack = consdata->maxactivity - lhs;
5492 
5493  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5494  * it to zero
5495  */
5496  if( !SCIPisPositive(scip, slack) )
5497  slack = 0.0;
5498 
5499  alpha = val * (ub - lb);
5500  assert(!SCIPisNegative(scip, alpha));
5501 
5502  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5503  {
5504  SCIP_Real newlb;
5505 
5506  /* compute new lower bound */
5507  newlb = ub - (slack / val);
5508 
5509  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5510 
5511  if( *cutoff )
5512  {
5513  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5514  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5515 
5516  return SCIP_OKAY;
5517  }
5518  }
5519  }
5520  }
5521  else
5522  {
5523  /* check, if we can tighten the variable's lower bound */
5524  if( !SCIPisInfinity(scip, rhs) )
5525  {
5526  SCIP_Real slack;
5527  SCIP_Real alpha;
5528 
5529  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5530  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5531  {
5532  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5533  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5534 
5535  *cutoff = TRUE;
5536  return SCIP_OKAY;
5537  }
5538 
5539  slack = rhs - consdata->minactivity;
5540 
5541  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5542  * it to zero
5543  */
5544  if( !SCIPisPositive(scip, slack) )
5545  slack = 0.0;
5546 
5547  alpha = val * (lb - ub);
5548  assert(!SCIPisNegative(scip, alpha));
5549 
5550  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5551  {
5552  SCIP_Real newlb;
5553 
5554  /* compute new lower bound */
5555  newlb = ub + slack / val;
5556 
5557  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5558 
5559  if( *cutoff )
5560  {
5561  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5562  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5563 
5564  return SCIP_OKAY;
5565  }
5566  /* collect the new lower bound which is needed for the upper bound computation */
5567  lb = SCIPvarGetLbLocal(var);
5568  }
5569  }
5570 
5571  /* check, if we can tighten the variable's upper bound */
5572  if( !SCIPisInfinity(scip, -lhs) )
5573  {
5574  SCIP_Real slack;
5575  SCIP_Real alpha;
5576 
5577  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5578  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5579  {
5580  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5581  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5582 
5583  *cutoff = TRUE;
5584  return SCIP_OKAY;
5585  }
5586 
5587  slack = consdata->maxactivity - lhs;
5588 
5589  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5590  * it to zero
5591  */
5592  if( !SCIPisPositive(scip, slack) )
5593  slack = 0.0;
5594 
5595  alpha = val * (lb - ub);
5596  assert(!SCIPisNegative(scip, alpha));
5597 
5598  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5599  {
5600  SCIP_Real newub;
5601 
5602  /* compute new upper bound */
5603  newub = lb - (slack / val);
5604 
5605  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5606 
5607  if( *cutoff )
5608  {
5609  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5610  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5611 
5612  return SCIP_OKAY;
5613  }
5614  }
5615  }
5616  }
5617 
5618  return SCIP_OKAY;
5619 }
5620 
5621 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5622 static
5624  SCIP* scip, /**< SCIP data structure */
5625  SCIP_CONS* cons, /**< conflict detecting constraint */
5626  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5627  int nvars, /**< number of variables reasoning the infeasibility */
5628  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5629  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5630  )
5631 {
5632 #ifndef NDEBUG
5633  SCIP_CONSDATA* consdata;
5634 
5635  assert(scip != NULL);
5636  assert(cons != NULL);
5637 
5638  consdata = SCIPconsGetData(cons);
5639  assert(consdata != NULL);
5640  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5641 #endif
5642 
5643  /* conflict analysis can only be applied in solving stage and if it is turned on */
5645  return SCIP_OKAY;
5646 
5647  /* initialize conflict analysis */
5649 
5650  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5651  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5652 
5653  /* add reasoning variables to conflict candidate queue which led to the conflict */
5654  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5655 
5656  /* analyze the conflict */
5657  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5658 
5659  return SCIP_OKAY;
5660 }
5661 
5662 /** propagate ranged rows
5663  *
5664  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5665  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5666  * variables better.
5667  *
5668  * Example:
5669  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5670  *
5671  * x3 needs to be a multiple of 3, so the instance is infeasible.
5672  *
5673  * Example:
5674  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5675  *
5676  * The only posible value for x3 is 2, so the variable will be fixed.
5677  *
5678  * @todo add holes if possible
5679  */
5680 static
5682  SCIP* scip, /**< SCIP data structure */
5683  SCIP_CONS* cons, /**< linear constraint */
5684  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5685  int* nfixedvars, /**< pointer to count number of fixed variables */
5686  int* nchgbds, /**< pointer to count the number of bound changes */
5687  int* naddconss /**< pointer to count number of added constraints */
5688  )
5689 {
5690  SCIP_CONSHDLRDATA* conshdlrdata;
5691  SCIP_CONSHDLR* conshdlr;
5692  SCIP_CONSDATA* consdata;
5693  SCIP_VAR** infcheckvars;
5694  SCIP_Real* infcheckvals;
5695  SCIP_Real minactinfvars;
5696  SCIP_Real maxactinfvars;
5697  SCIP_Real lb;
5699  SCIP_Real feastol;
5700  SCIP_Real fixedact;
5701  SCIP_Real lhs;
5702  SCIP_Real rhs;
5703  SCIP_Real absminbincoef;
5704  SCIP_Longint gcd;
5705  SCIP_Longint gcdtmp;
5706  SCIP_Bool minactinfvarsinvalid;
5707  SCIP_Bool maxactinfvarsinvalid;
5708  SCIP_Bool possiblegcd;
5709  SCIP_Bool gcdisone;
5710  SCIP_Bool addartconss;
5711  int ninfcheckvars;
5712  int nunfixedvars;
5713  int nfixedconsvars;
5714  int ncontvars;
5715  int pos;
5716  int v;
5717 
5718  assert(scip != NULL);
5719  assert(cons != NULL);
5720  assert(cutoff != NULL);
5721  assert(nfixedvars != NULL);
5722  assert(nchgbds != NULL);
5723  assert(naddconss != NULL);
5724 
5725  /* modifiable constraint can be changed so we do not have all necessary information */
5726  if( SCIPconsIsModifiable(cons) )
5727  return SCIP_OKAY;
5728 
5729  consdata = SCIPconsGetData(cons);
5730  assert(consdata != NULL);
5731 
5732  /* we already did full ranged row propagation */
5733  if( consdata->rangedrowpropagated == 2 )
5734  return SCIP_OKAY;
5735 
5736  /* at least three variables are needed */
5737  if( consdata->nvars < 3 )
5738  return SCIP_OKAY;
5739 
5740  /* do nothing on normal inequalities */
5741  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5742  return SCIP_OKAY;
5743 
5744  /* get constraint handler data */
5745  conshdlr = SCIPconsGetHdlr(cons);
5746  assert(conshdlr != NULL);
5747  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5748  assert(conshdlrdata != NULL);
5749 
5750  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5751 
5752  /* we may add artificial constraints */
5753  if( addartconss )
5754  consdata->rangedrowpropagated = 2;
5755  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5756  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5757  * artificial constraints
5758  */
5759  else
5760  {
5761  if( consdata->rangedrowpropagated > 0 )
5762  return SCIP_OKAY;
5763 
5764  consdata->rangedrowpropagated = 1;
5765  }
5766  fixedact = 0;
5767  nfixedconsvars = 0;
5768  /* calculate fixed activity and number of fixed variables */
5769  for( v = consdata->nvars - 1; v >= 0; --v )
5770  {
5771  /* all zero coefficients should be eliminated */
5772  assert(!SCIPisZero(scip, consdata->vals[v]));
5773 
5774  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5775  {
5776  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5777  ++nfixedconsvars;
5778  }
5779  }
5780 
5781  /* do not work with huge fixed activities */
5782  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5783  return SCIP_OKAY;
5784 
5785  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5786  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5787  lhs = consdata->lhs - fixedact;
5788  rhs = consdata->rhs - fixedact;
5789  nunfixedvars = consdata->nvars - nfixedconsvars;
5790 
5791  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5792  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5793  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5794 
5795  absminbincoef = SCIP_REAL_MAX;
5796  ncontvars = 0;
5797  gcdisone = TRUE;
5798  possiblegcd = TRUE;
5799 
5800  /* we now partition all unfixed variables in two groups:
5801  *
5802  * the first one contains all integral variable with integral
5803  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5804  * given
5805  *
5806  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5807  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5808  */
5809 
5810  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5811  * variables
5812  */
5813  ninfcheckvars = 0;
5814  v = -1;
5815  pos = -1;
5816  do
5817  {
5818  ++v;
5819 
5820  /* partition the variables, do not change the order of collection, because it might be used later on */
5821  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5822  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5823  {
5824  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5825  {
5826  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5827  {
5828  ++ncontvars;
5829  }
5830  else if( SCIPvarIsBinary(consdata->vars[v]) )
5831  {
5832  SCIP_Real absval;
5833 
5834  absval = REALABS(consdata->vals[v]);
5835 
5836  if( absminbincoef > absval )
5837  absminbincoef = absval;
5838  }
5839 
5840  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5841  possiblegcd = FALSE;
5842  infcheckvars[ninfcheckvars] = consdata->vars[v];
5843  infcheckvals[ninfcheckvars] = consdata->vals[v];
5844  ++ninfcheckvars;
5845 
5846  if( pos == -1 )
5847  pos = v;
5848  }
5849  ++v;
5850  }
5851  }
5852  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5853 
5854  /* if the first group of variables is empty, we stop */
5855  /* @todo try to propagate/split up a constraint of the form:
5856  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5857  * with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1]
5858  */
5859  if( v == consdata->nvars )
5860  goto TERMINATE;
5861 
5862  /* we need at least two non-continuous variables */
5863  if( ncontvars + 2 > nunfixedvars )
5864  goto TERMINATE;
5865 
5866  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5867  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5868 
5869  feastol = SCIPfeastol(scip);
5870 
5871  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5872  assert(gcd >= 2);
5873 
5874  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5875  * calculate gcd over the first part of variables */
5876  for( ; v < consdata->nvars; ++v )
5877  {
5878  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5879  continue;
5880 
5881  if( SCIPvarIsBinary(consdata->vars[v]) )
5882  {
5883  SCIP_Real absval;
5884 
5885  absval = REALABS(consdata->vals[v]);
5886 
5887  if( absminbincoef > absval )
5888  absminbincoef = absval;
5889  }
5890 
5891  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5892  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5893  {
5894  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5895  ++ncontvars;
5896 
5897  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5898  possiblegcd = FALSE;
5899  infcheckvars[ninfcheckvars] = consdata->vars[v];
5900  infcheckvals[ninfcheckvars] = consdata->vals[v];
5901 
5902  ++ninfcheckvars;
5903 
5904  if( pos == -1 )
5905  pos = v;
5906  }
5907  else
5908  {
5909  assert(REALABS(consdata->vals[v]) > 1.5);
5910 
5911  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5912  assert(gcdtmp >= 1);
5913 
5914  if( gcdtmp == 1 )
5915  {
5916  infcheckvars[ninfcheckvars] = consdata->vars[v];
5917  infcheckvals[ninfcheckvars] = consdata->vals[v];
5918 
5919  ++ninfcheckvars;
5920 
5921  if( pos == -1 )
5922  pos = v;
5923  }
5924  else
5925  gcd = gcdtmp;
5926  }
5927  }
5928  assert(gcd >= 2);
5929 
5930  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5931  * normalizeCons() */
5932  if( ninfcheckvars == 0 )
5933  goto TERMINATE;
5934 
5935  assert(pos >= 0);
5936 
5937  minactinfvarsinvalid = FALSE;
5938  maxactinfvarsinvalid = FALSE;
5939  maxactinfvars = 0.0;
5940  minactinfvars = 0.0;
5941 
5942  /* calculate activities over all infcheckvars */
5943  for( v = ninfcheckvars - 1; v >= 0; --v )
5944  {
5945  lb = SCIPvarGetLbLocal(infcheckvars[v]);
5946  ub = SCIPvarGetUbLocal(infcheckvars[v]);
5947 
5948  if( SCIPisInfinity(scip, -lb) )
5949  {
5950  if( infcheckvals[v] < 0.0 )
5951  maxactinfvarsinvalid = TRUE;
5952  else
5953  minactinfvarsinvalid = TRUE;
5954  }
5955  else
5956  {
5957  if( infcheckvals[v] < 0.0 )
5958  maxactinfvars += infcheckvals[v] * lb;
5959  else
5960  minactinfvars += infcheckvals[v] * lb;
5961  }
5962 
5963  if( SCIPisInfinity(scip, ub) )
5964  {
5965  if( infcheckvals[v] > 0.0 )
5966  maxactinfvarsinvalid = TRUE;
5967  else
5968  minactinfvarsinvalid = TRUE;
5969  }
5970  else
5971  {
5972  if( infcheckvals[v] > 0.0 )
5973  maxactinfvars += infcheckvals[v] * ub;
5974  else
5975  minactinfvars += infcheckvals[v] * ub;
5976  }
5977 
5978  /* better abort on to big values */
5979  if( SCIPisHugeValue(scip, -minactinfvars) )
5980  minactinfvarsinvalid = TRUE;
5981  if( SCIPisHugeValue(scip, maxactinfvars) )
5982  maxactinfvarsinvalid = TRUE;
5983 
5984  if( minactinfvarsinvalid || maxactinfvarsinvalid )
5985  goto TERMINATE;
5986  }
5987  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
5988 
5989  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
5990  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
5991 
5992  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
5993  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
5994  * activities */
5995  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
5996  * !!!note!!!
5997  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
5998  * are not at their global bound
5999  */
6000 
6001  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6002  * infeasibility */
6003  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6004  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6005  {
6006  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6007  SCIPdebugPrintCons(scip, cons, NULL);
6008 
6009  /* start conflict analysis */
6010  /* @todo improve conflict analysis by adding relaxed bounds */
6011  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6012 
6013  *cutoff = TRUE;
6014  }
6015  else if( ncontvars == 0 )
6016  {
6017  SCIP_Longint gcdinfvars = -1;
6018 
6019  /* check for gcd over all infcheckvars */
6020  if( possiblegcd )
6021  {
6022  v = ninfcheckvars - 1;
6023  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6024  assert(gcdinfvars >= 2);
6025 
6026  for( ; v >= 0 && gcdinfvars >= 2; --v )
6027  {
6028  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6029  }
6030  }
6031  else if( gcdisone )
6032  gcdinfvars = 1;
6033 
6034  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6035 
6036  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6037  if( gcdinfvars >= 1 )
6038  {
6039  SCIP_Real value;
6040  SCIP_Real value2;
6041  SCIP_Real minvalue = SCIP_INVALID;
6042  SCIP_Real maxvalue = SCIP_INVALID;
6043  int nsols = 0;
6044 
6045  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6046 
6047  /* check how many possible solutions exist */
6048  while( SCIPisLE(scip, value, maxactinfvars) )
6049  {
6050  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6051 
6052  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6053  {
6054  ++nsols;
6055 
6056  /* early termination if we found more than two solutions */
6057  if( nsols == 3 )
6058  break;
6059 
6060  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6061  minvalue = value;
6062 
6063  maxvalue = value;
6064  }
6065  value += gcdinfvars;
6066  }
6067  assert(nsols < 2 || minvalue <= maxvalue);
6068 
6069  /* determine last possible solution for better bounding */
6070  if( nsols == 3 )
6071  {
6072 #ifndef NDEBUG
6073  SCIP_Real secondsolval = maxvalue;
6074 #endif
6075  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6076 
6077  /* check how many possible solutions exist */
6078  while( SCIPisGE(scip, value, minactinfvars) )
6079  {
6080  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6081 
6082  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6083  {
6084  maxvalue = value;
6085  assert(maxvalue > minvalue);
6086  break;
6087  }
6088  value -= gcdinfvars;
6089  }
6090  assert(maxvalue > secondsolval);
6091  }
6092 
6093  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6094  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6095 
6096  /* no possible solution found */
6097  if( nsols == 0 )
6098  {
6099  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6100  gcdinfvars, gcd, lhs, rhs);
6101  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6102  SCIPdebugPrintCons(scip, cons, NULL);
6103 
6104  /* start conflict analysis */
6105  /* @todo improve conflict analysis by adding relaxed bounds */
6106  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6107 
6108  *cutoff = TRUE;
6109  }
6110  /* if only one solution exist we can extract a new constraint or fix variables */
6111  else if( nsols == 1 )
6112  {
6113  assert(minvalue == maxvalue); /*lint !e777*/
6114 
6115  /* we can fix the only variable in our second set of variables */
6116  if( ninfcheckvars == 1 )
6117  {
6118  SCIP_Bool fixed;
6119 
6120  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6121 
6122  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6123  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6124  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6125 
6126  /* fix variable to only possible value */
6127  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6128  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6129 
6130  if( *cutoff )
6131  {
6132  /* start conflict analysis */
6133  /* @todo improve conflict analysis by adding relaxed bounds */
6134  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6135  }
6136 
6137  if( fixed )
6138  ++(*nfixedvars);
6139  }
6140  else
6141  {
6142  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6143  if( ninfcheckvars == nunfixedvars - 1 )
6144  {
6145  SCIP_Real bound;
6146  SCIP_Bool foundvar = FALSE;
6147  SCIP_Bool fixed;
6148  int w = 0;
6149 
6150  assert(ninfcheckvars > 0);
6151 
6152  /* find variable which is not an infcheckvar and fix it */
6153  for( v = 0; v < consdata->nvars - 1; ++v )
6154  {
6155  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6156  {
6157  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6158  {
6159 #ifndef NDEBUG
6160  int v2 = v + 1;
6161  int w2 = w;
6162 
6163  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6164 
6165  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6166  {
6167  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6168  continue;
6169 
6170  assert(consdata->vars[v2] == infcheckvars[w2]);
6171  ++w2;
6172  }
6173  assert(w2 == ninfcheckvars);
6174 #endif
6175  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6176 
6177  foundvar = TRUE;
6178 
6179  if( consdata->vals[v] < 0 )
6180  {
6181  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6182  }
6183  else
6184  {
6185  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6186  }
6187 
6188  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6189  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6190  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6191 
6192  /* fix variable to only possible value */
6193  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6194  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6195 
6196  if( *cutoff )
6197  {
6198  /* start conflict analysis */
6199  /* @todo improve conflict analysis by adding relaxed bounds */
6200  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6201  consdata->vars[v], bound) );
6202  }
6203 
6204  if( fixed )
6205  ++(*nfixedvars);
6206 
6207  break;
6208  }
6209 
6210  ++w;
6211  }
6212  }
6213 
6214  /* maybe last variable was the not infcheckvar */
6215  if( !foundvar )
6216  {
6217  assert(v == consdata->nvars - 1);
6218  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6219 
6220  if( consdata->vals[v] < 0 )
6221  {
6222  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6223  }
6224  else
6225  {
6226  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6227  }
6228 
6229  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6230  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6231  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6232 
6233  /* fix variable to only possible value */
6234  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6235  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6236 
6237  if( *cutoff )
6238  {
6239  /* start conflict analysis */
6240  /* @todo improve conflict analysis by adding relaxed bounds */
6241  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6242  consdata->vars[v], bound) );
6243  }
6244 
6245  if( fixed )
6246  ++(*nfixedvars);
6247  }
6248  }
6249  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6250  {
6251  /* aggregation possible if we have two variables, but this will be done later on */
6252  SCIP_CONS* newcons;
6253  char name[SCIP_MAXSTRLEN];
6254 
6255  /* create, add, and release new artificial constraint */
6256  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6257  ++conshdlrdata->naddconss;
6258 
6259  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6260 
6261  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6262  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6263  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6264 
6265  SCIPdebugPrintCons(scip, newcons, NULL);
6266 
6267  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6268 
6269  ++(*naddconss);
6270  }
6271  }
6272  }
6273  /* at least two solutions */
6274  else
6275  {
6276  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6277 
6278  /* only one variable in the second set, so we can bound this variables */
6279  if( ninfcheckvars == 1 )
6280  {
6281  SCIP_Bool tightened;
6282  SCIP_Real newlb;
6283  SCIP_Real newub;
6284 
6285  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6286 
6287  if( infcheckvals[0] < 0 )
6288  {
6289  newlb = maxvalue/infcheckvals[0];
6290  newub = minvalue/infcheckvals[0];
6291  }
6292  else
6293  {
6294  newlb = minvalue/infcheckvals[0];
6295  newub = maxvalue/infcheckvals[0];
6296  }
6297  assert(newlb < newub);
6298 
6299  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6300  {
6301  /* update lower bound of variable */
6302  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6303  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6304 
6305  /* tighten variable lower bound to minimal possible value */
6306  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6307  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6308 
6309  if( *cutoff )
6310  {
6311  /* start conflict analysis */
6312  /* @todo improve conflict analysis by adding relaxed bounds */
6313  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6314  }
6315 
6316  if( tightened )
6317  ++(*nchgbds);
6318  }
6319 
6320  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6321  {
6322  /* update upper bound of variable */
6323  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6324  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6325 
6326  /* tighten variable upper bound to maximal possible value */
6327  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6328  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6329 
6330  if( *cutoff )
6331  {
6332  /* start conflict analysis */
6333  /* @todo improve conflict analysis by adding relaxed bounds */
6334  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6335  }
6336 
6337  if( tightened )
6338  ++(*nchgbds);
6339  }
6340  }
6341  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6342  else if( ninfcheckvars == nunfixedvars - 1 )
6343  {
6344  SCIP_Bool foundvar = FALSE;
6345  SCIP_Bool tightened;
6346  SCIP_Real newlb;
6347  SCIP_Real newub;
6348  int w = 0;
6349 
6350  assert(ninfcheckvars > 0);
6351  assert(minvalue < maxvalue);
6352 
6353  /* find variable which is not an infcheckvar and fix it */
6354  for( v = 0; v < consdata->nvars - 1; ++v )
6355  {
6356  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6357  {
6358  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6359  {
6360 #ifndef NDEBUG
6361  int v2 = v + 1;
6362  int w2 = w;
6363 
6364  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6365 
6366  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6367  {
6368  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6369  continue;
6370 
6371  assert(consdata->vars[v2] == infcheckvars[w2]);
6372  ++w2;
6373  }
6374  assert(w2 == ninfcheckvars);
6375 #endif
6376 
6377  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6378  foundvar = TRUE;
6379 
6380  if( consdata->vals[v] < 0 )
6381  {
6382  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6383  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6384  }
6385  else
6386  {
6387  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6388  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6389  }
6390  assert(SCIPisLE(scip, newlb, newub));
6391 
6392  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6393  {
6394  /* update lower bound of variable */
6395  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6396  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6397 
6398  /* tighten variable lower bound to minimal possible value */
6399  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6400  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6401 
6402  if( *cutoff )
6403  {
6404  /* start conflict analysis */
6405  /* @todo improve conflict analysis by adding relaxed bounds */
6406  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6407  consdata->vars[v], newlb) );
6408  }
6409 
6410  if( tightened )
6411  ++(*nchgbds);
6412  }
6413 
6414  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6415  {
6416  /* update upper bound of variable */
6417  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6418  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6419 
6420  /* tighten variable upper bound to maximal possible value */
6421  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6422  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6423 
6424  if( *cutoff )
6425  {
6426  /* start conflict analysis */
6427  /* @todo improve conflict analysis by adding relaxed bounds */
6428  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6429  consdata->vars[v], newub) );
6430  }
6431 
6432  if( tightened )
6433  ++(*nchgbds);
6434  }
6435 
6436  break;
6437  }
6438 
6439  ++w;
6440  }
6441  }
6442 
6443  /* maybe last variable was the not infcheckvar */
6444  if( !foundvar )
6445  {
6446  assert(v == consdata->nvars - 1);
6447  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6448 
6449  if( consdata->vals[v] < 0 )
6450  {
6451  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6452  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6453  }
6454  else
6455  {
6456  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6457  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6458  }
6459  assert(SCIPisLE(scip, newlb, newub));
6460 
6461  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6462  {
6463  /* update lower bound of variable */
6464  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6465  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6466 
6467  /* tighten variable lower bound to minimal possible value */
6468  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6469  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6470 
6471  if( *cutoff )
6472  {
6473  /* start conflict analysis */
6474  /* @todo improve conflict analysis by adding relaxed bounds */
6475  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6476  }
6477 
6478  if( tightened )
6479  ++(*nchgbds);
6480  }
6481 
6482  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6483  {
6484  /* update upper bound of variable */
6485  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6486  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6487 
6488  /* tighten variable upper bound to maximal possible value */
6489  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6490  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6491 
6492  if( *cutoff )
6493  {
6494  /* start conflict analysis */
6495  /* @todo improve conflict analysis by adding relaxed bounds */
6496  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6497  }
6498 
6499  if( tightened )
6500  ++(*nchgbds);
6501  }
6502  }
6503  }
6504  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6505  * region for our infcheckvars, if possible
6506  */
6507  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6508  {
6509  SCIP_CONS* newcons;
6510  char name[SCIP_MAXSTRLEN];
6511  SCIP_Real newlhs;
6512  SCIP_Real newrhs;
6513 
6514  assert(maxvalue > minvalue);
6515 
6516  if( SCIPisGT(scip, minvalue, minactinfvars) )
6517  newlhs = minvalue;
6518  else
6519  newlhs = -SCIPinfinity(scip);
6520 
6521  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6522  newrhs = maxvalue;
6523  else
6524  newrhs = SCIPinfinity(scip);
6525 
6526  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6527  {
6528  /* create, add, and release new artificial constraint */
6529  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6530  ++conshdlrdata->naddconss;
6531 
6532  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6533 
6534  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6535  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6536  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6537 
6538  SCIPdebugPrintCons(scip, newcons, NULL);
6539  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6540 
6541  ++(*naddconss);
6542  }
6543  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6544  * should be maxvalue */
6545  }
6546  }
6547  }
6548  }
6549  else if( addartconss && ncontvars < ninfcheckvars )
6550  {
6551  SCIP_Real maxact = 0.0;
6552  SCIP_Real minact = 0.0;
6553  int w = 0;
6554 
6555  /* compute activities of non-infcheckvars */
6556  for( v = 0; v < consdata->nvars; ++v )
6557  {
6558  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6559  {
6560  ++w;
6561  continue;
6562  }
6563 
6564  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6565  {
6566  if( SCIPvarIsBinary(consdata->vars[v]) )
6567  {
6568  if( consdata->vals[v] > 0.0 )
6569  maxact += consdata->vals[v];
6570  else
6571  minact += consdata->vals[v];
6572  }
6573  else
6574  {
6575  SCIP_Real tmpval;
6576 
6577  assert(SCIPvarIsIntegral(consdata->vars[v]));
6578 
6579  if( consdata->vals[v] > 0.0 )
6580  {
6581  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6582 
6583  if( SCIPisHugeValue(scip, -tmpval) )
6584  break;
6585 
6586  minact += tmpval;
6587 
6588  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6589 
6590  if( SCIPisHugeValue(scip, tmpval) )
6591  break;
6592 
6593  maxact += tmpval;
6594  }
6595  else
6596  {
6597  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6598 
6599  if( SCIPisHugeValue(scip, -tmpval) )
6600  break;
6601 
6602  minact += tmpval;
6603 
6604  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6605 
6606  if( SCIPisHugeValue(scip, tmpval) )
6607  break;
6608 
6609  maxact += tmpval;
6610  }
6611  }
6612  }
6613  }
6614  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6615  {
6616  SCIP_CONS* newcons;
6617  char name[SCIP_MAXSTRLEN];
6618  SCIP_Real newlhs;
6619  SCIP_Real newrhs;
6620 
6621  assert(maxact > minact);
6622  assert(w == ninfcheckvars);
6623 
6624  newlhs = lhs - maxact;
6625  newrhs = rhs - minact;
6626  assert(newlhs < newrhs);
6627 
6628  /* create, add, and release new artificial constraint */
6629  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6630  ++conshdlrdata->naddconss;
6631 
6632  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6633 
6634  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6635  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6636  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6637 
6638  SCIPdebugPrintCons(scip, newcons, NULL);
6639  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6640 
6641  ++(*naddconss);
6642  }
6643  }
6644 
6645  TERMINATE:
6646  SCIPfreeBufferArray(scip, &infcheckvals);
6647  SCIPfreeBufferArray(scip, &infcheckvars);
6648 
6649  return SCIP_OKAY;
6650 }
6651 
6652 /** tightens bounds of a single variable due to activity bounds */
6653 static
6655  SCIP* scip, /**< SCIP data structure */
6656  SCIP_CONS* cons, /**< linear constraint */
6657  int pos, /**< position of the variable in the vars array */
6658  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6659  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6660  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6661  )
6662 {
6663  SCIP_CONSDATA* consdata;
6664  SCIP_VAR* var;
6665  SCIP_Real val;
6666  SCIP_Real lb;
6667  SCIP_Real ub;
6668  SCIP_Real minresactivity;
6669  SCIP_Real maxresactivity;
6670  SCIP_Real lhs;
6672  SCIP_Bool infeasible;
6673  SCIP_Bool tightened;
6674  SCIP_Bool minisrelax;
6675  SCIP_Bool maxisrelax;
6676  SCIP_Bool isminsettoinfinity;
6677  SCIP_Bool ismaxsettoinfinity;
6678 
6679  assert(scip != NULL);
6680  assert(cons != NULL);
6681  assert(cutoff != NULL);
6682  assert(nchgbds != NULL);
6683 
6684  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6685  if( SCIPconsIsModifiable(cons) )
6686  return SCIP_OKAY;
6687 
6688  consdata = SCIPconsGetData(cons);
6689  assert(consdata != NULL);
6690  assert(0 <= pos && pos < consdata->nvars);
6691 
6692  *cutoff = FALSE;
6693 
6694  var = consdata->vars[pos];
6695 
6696  /* we cannot tighten bounds of multi-aggregated variables */
6698  return SCIP_OKAY;
6699 
6700  val = consdata->vals[pos];
6701  lhs = consdata->lhs;
6702  rhs = consdata->rhs;
6703  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6704  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6705  assert(var != NULL);
6706  assert(!SCIPisZero(scip, val));
6707  assert(!SCIPisInfinity(scip, lhs));
6708  assert(!SCIPisInfinity(scip, -rhs));
6709 
6710  lb = SCIPvarGetLbLocal(var);
6711  ub = SCIPvarGetUbLocal(var);
6712  assert(SCIPisLE(scip, lb, ub));
6713 
6714  if( val > 0.0 )
6715  {
6716  /* check, if we can tighten the variable's bounds */
6717  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6718  {
6719  SCIP_Real newub;
6720 
6721  newub = (rhs - minresactivity)/val;
6722 
6723  if( !SCIPisInfinity(scip, newub) &&
6724  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6725  {
6726  SCIP_Bool activityunreliable;
6727  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6728 
6729  /* check minresactivities for reliability */
6730  if( activityunreliable )
6731  {
6732  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6733  newub = (rhs - minresactivity)/val;
6734  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6735  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6736  && (!force || !SCIPisLT(scip, newub, ub)));
6737  }
6738 
6739  if( !activityunreliable )
6740  {
6741  /* tighten upper bound */
6742  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6743  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6744  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6745  &infeasible, &tightened) );
6746  if( infeasible )
6747  {
6748  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6749  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6750 
6751  /* analyze conflict */
6752  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6753 
6754  *cutoff = TRUE;
6755  return SCIP_OKAY;
6756  }
6757  if( tightened )
6758  {
6759  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6760  assert(SCIPisFeasLE(scip, ub, newub));
6761  (*nchgbds)++;
6762 
6763  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6764  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6765  }
6766  }
6767  }
6768  }
6769 
6770  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6771  {
6772  SCIP_Real newlb;
6773 
6774  newlb = (lhs - maxresactivity)/val;
6775  if( !SCIPisInfinity(scip, -newlb) &&
6776  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6777  {
6778  /* check maxresactivities for reliability */
6779  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6780  {
6781  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6782  newlb = (lhs - maxresactivity)/val;
6783 
6784  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6785  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6786  && (!force || !SCIPisGT(scip, newlb, lb))) )
6787  return SCIP_OKAY;
6788  }
6789 
6790  /* tighten lower bound */
6791  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6792  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6793  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6794  &infeasible, &tightened) );
6795  if( infeasible )
6796  {
6797  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6798  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6799 
6800  /* analyze conflict */
6801  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6802 
6803  *cutoff = TRUE;
6804  return SCIP_OKAY;
6805  }
6806  if( tightened )
6807  {
6808  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6809  assert(SCIPisFeasGE(scip, lb, newlb));
6810  (*nchgbds)++;
6811  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6812  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6813  }
6814  }
6815  }
6816  }
6817  else
6818  {
6819  /* check, if we can tighten the variable's bounds */
6820  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6821  {
6822  SCIP_Real newlb;
6823 
6824  newlb = (rhs - minresactivity)/val;
6825  if( !SCIPisInfinity(scip, -newlb) &&
6826  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6827  {
6828  SCIP_Bool activityunreliable;
6829  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6830  /* check minresactivities for reliability */
6831  if( activityunreliable )
6832  {
6833  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6834  newlb = (rhs - minresactivity)/val;
6835 
6836  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6837  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6838  && (!force || !SCIPisGT(scip, newlb, lb)));
6839  }
6840 
6841  if( !activityunreliable )
6842  {
6843  /* tighten lower bound */
6844  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6845  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6846  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6847  &infeasible, &tightened) );
6848  if( infeasible )
6849  {
6850  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6851  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6852 
6853  /* analyze conflict */
6854  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6855 
6856  *cutoff = TRUE;
6857  return SCIP_OKAY;
6858  }
6859  if( tightened )
6860  {
6861  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6862  assert(SCIPisFeasGE(scip, lb, newlb));
6863  (*nchgbds)++;
6864  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6865  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6866  }
6867  }
6868  }
6869  }
6870 
6871  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6872  {
6873  SCIP_Real newub;
6874 
6875  newub = (lhs - maxresactivity)/val;
6876  if( !SCIPisInfinity(scip, newub) &&
6877  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6878  {
6879  /* check maxresactivities for reliability */
6880  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6881  {
6882  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6883  newub = (lhs - maxresactivity)/val;
6884 
6885  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6886  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6887  && (!force || !SCIPisLT(scip, newub, ub))) )
6888  return SCIP_OKAY;
6889  }
6890 
6891  /* tighten upper bound */
6892  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6893  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6894  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6895  &infeasible, &tightened) );
6896  if( infeasible )
6897  {
6898  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6899  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6900 
6901  /* analyze conflict */
6902  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6903 
6904  *cutoff = TRUE;
6905  return SCIP_OKAY;
6906  }
6907  if( tightened )
6908  {
6909  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6910  assert(SCIPisFeasLE(scip, ub, newub));
6911  (*nchgbds)++;
6912  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6913  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6914  }
6915  }
6916  }
6917  }
6918 
6919  return SCIP_OKAY;
6920 }
6921 
6922 #define MAXTIGHTENROUNDS 10
6923 
6924 /** tightens bounds of variables in constraint due to activity bounds */
6925 static
6927  SCIP* scip, /**< SCIP data structure */
6928  SCIP_CONS* cons, /**< linear constraint */
6929  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6930  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6931  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6932  int* nchgbds /**< pointer to count the total number of tightened bounds */
6933  )
6934 {
6935  SCIP_CONSDATA* consdata;
6936  unsigned int tightenmode;
6937  int nvars;
6938  int nrounds;
6939  int lastchange;
6940  int oldnchgbds;
6941 #ifndef SCIP_DEBUG
6942  int oldnchgbdstotal;
6943 #endif
6944  int v;
6945  SCIP_Bool force;
6946  SCIP_Bool easycase;
6947 
6948  assert(scip != NULL);
6949  assert(cons != NULL);
6950  assert(nchgbds != NULL);
6951  assert(cutoff != NULL);
6952 
6953  *cutoff = FALSE;
6954 
6955  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6956  if( SCIPconsIsModifiable(cons) )
6957  return SCIP_OKAY;
6958 
6959  /* if a constraint was created after presolve, then it may hold fixed variables
6960  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
6961  * thus, ensure here again that variable fixings have been applied
6962  */
6963  SCIP_CALL( applyFixings(scip, cons, cutoff) );
6964  if( *cutoff )
6965  return SCIP_OKAY;
6966 
6967  /* check if constraint has any chances of tightening bounds */
6968  if( !canTightenBounds(scip, cons) )
6969  return SCIP_OKAY;
6970 
6971  consdata = SCIPconsGetData(cons);
6972  assert(consdata != NULL);
6973 
6974  nvars = consdata->nvars;
6975  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
6976 
6977  /* we are at the root node or during presolving */
6978  if( SCIPgetDepth(scip) < 1 )
6979  tightenmode = 2;
6980  else
6981  tightenmode = 1;
6982 
6983  /* stop if we already tightened the constraint and the tightening is not forced */
6984  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
6985  return SCIP_OKAY;
6986 
6987  /* ensure that the variables are properly sorted */
6988  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
6989  {
6990  SCIP_CALL( consdataSort(scip, consdata) );
6991  assert(consdata->binvarssorted);
6992  }
6993 
6994  /* update maximal activity delta if necessary */
6995  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
6996  consdataRecomputeMaxActivityDelta(scip, consdata);
6997 
6998  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
6999  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7000  checkMaxActivityDelta(scip, consdata);
7001 
7002  /* this may happen if all variables are fixed */
7003  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7004  return SCIP_OKAY;
7005 
7006  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7007  {
7008  SCIP_Real slack;
7009  SCIP_Real surplus;
7010  SCIP_Real minactivity;
7011  SCIP_Real maxactivity;
7012  SCIP_Bool minisrelax;
7013  SCIP_Bool maxisrelax;
7014 
7015  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7016  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
7017  assert(!SCIPisInfinity(scip, minactivity));
7018  assert(!SCIPisInfinity(scip, -maxactivity));
7019 
7020  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7021  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7022 
7023  /* check if the constraint will propagate */
7024  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7025  return SCIP_OKAY;
7026  }
7027 
7028  /* check if we can use fast implementation for easy and numerically well behaved cases */
7029  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7030 
7031  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7032  lastchange = -1;
7033  oldnchgbds = 0;
7034 
7035 #ifndef SCIP_DEBUG
7036  oldnchgbdstotal = *nchgbds;
7037 #endif
7038 
7039  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7040  {
7041  /* mark the constraint to have the variables' bounds tightened */
7042  consdata->boundstightened = (unsigned int)tightenmode;
7043 
7044  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7045  * sorting enables skipping variables
7046  */
7047  v = 0;
7048  while( v < nvars && v != lastchange && !(*cutoff) )
7049  {
7050  oldnchgbds = *nchgbds;
7051 
7052  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
7053 
7054  if( easycase )
7055  {
7056  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7057  }
7058  else
7059  {
7060  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7061  }
7062 
7063  /* if there was no progress, skip the rest of the binary variables */
7064  if( *nchgbds > oldnchgbds )
7065  {
7066  lastchange = v;
7067  ++v;
7068  }
7069  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
7070  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7071  v = consdata->nbinvars;
7072  else
7073  ++v;
7074  }
7075 
7076 #ifndef SCIP_DEBUG
7077  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7078  *nchgbds - oldnchgbdstotal, nrounds);
7079  oldnchgbdstotal += oldnchgbds;
7080 #endif
7081  }
7082 
7083 #ifndef NDEBUG
7084  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7085  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7086 #endif
7087 
7088  return SCIP_OKAY;
7089 }
7090 
7091 /** checks linear constraint for feasibility of given solution or current solution */
7092 static
7094  SCIP* scip, /**< SCIP data structure */
7095  SCIP_CONS* cons, /**< linear constraint */
7096  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7097  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7098  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7099  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7100  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7101  )
7102 {
7103  SCIP_CONSDATA* consdata;
7104  SCIP_Real activity;
7105  SCIP_Real absviol;
7106  SCIP_Real relviol;
7107  SCIP_Real lhsviol;
7108  SCIP_Real rhsviol;
7109 
7110  assert(scip != NULL);
7111  assert(cons != NULL);
7112  assert(violated != NULL);
7113 
7114  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7115  SCIPdebugPrintCons(scip, cons, NULL);
7116 
7117  consdata = SCIPconsGetData(cons);
7118  assert(consdata != NULL);
7119 
7120  *violated = FALSE;
7121 
7122  if( consdata->row != NULL )
7123  {
7124  if( !checklprows && SCIProwIsInLP(consdata->row) )
7125  return SCIP_OKAY;
7126  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7127  activity = consdataComputePseudoActivity(scip, consdata);
7128  else
7129  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7130  }
7131  else
7132  activity = consdataGetActivity(scip, consdata, sol);
7133 
7134  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7135  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7136  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7137  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7138 
7139  /* calculate absolute and relative bound violations */
7140  lhsviol = consdata->lhs - activity;
7141  rhsviol = activity - consdata->rhs;
7142 
7143  absviol = 0.0;
7144  relviol = 0.0;
7145  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7146  {
7147  absviol = lhsviol;
7148  relviol = SCIPrelDiff(consdata->lhs, activity);
7149  }
7150  else if( rhsviol > 0 )
7151  {
7152  absviol = rhsviol;
7153  relviol = SCIPrelDiff(activity, consdata->rhs);
7154  }
7155 
7156  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7157  * return infeasible for safety
7158  */
7159  if( activity == SCIP_INVALID ) /*lint !e777*/
7160  {
7161  assert(sol == NULL);
7162  *violated = TRUE;
7163 
7164  /* set violation of invalid pseudo solutions */
7165  absviol = SCIP_INVALID;
7166  relviol = SCIP_INVALID;
7167 
7168  /* reset constraint age since we are in enforcement */
7169  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7170  }
7171  /* check with relative tolerances (the default) */
7172  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7173  {
7174  /* the "normal" check: one of the two sides is violated */
7175  if( !checkrelmaxabs )
7176  {
7177  *violated = TRUE;
7178 
7179  /* only reset constraint age if we are in enforcement */
7180  if( sol == NULL )
7181  {
7182  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7183  }
7184  }
7185  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7186  * small compared to the absolute values occurring in the activity
7187  */
7188  else
7189  {
7190  SCIP_Real maxabs;
7191  SCIP_Real coef;
7192  SCIP_Real absval;
7193  SCIP_Real solval;
7194  int v;
7195 
7196  maxabs = 1.0;
7197 
7198  /* compute maximum absolute value */
7199  for( v = 0; v < consdata->nvars; ++v )
7200  {
7201  if( consdata->vals != NULL )
7202  {
7203  coef = consdata->vals[v];
7204  }
7205  else
7206  coef = 1.0;
7207 
7208  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7209  absval = REALABS( coef * solval );
7210  maxabs = MAX( maxabs, absval );
7211  }
7212 
7213  /* regard left hand side, first */
7214  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7215  {
7216  /* check whether violation is random noise */
7217  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7218  {
7219  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7220  consdata->lhs - activity, maxabs);
7221  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7222 
7223  /* only increase constraint age if we are in enforcement */
7224  if( sol == NULL )
7225  {
7226  SCIP_CALL( SCIPincConsAge(scip, cons) );
7227  }
7228  }
7229  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7230  else if( SCIPisZero(scip, consdata->lhs) )
7231  {
7232  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7233  {
7234  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7235  consdata->lhs - activity, maxabs);
7236  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7237 
7238  /* only increase constraint age if we are in enforcement */
7239  if( sol == NULL )
7240  {
7241  SCIP_CALL( SCIPincConsAge(scip, cons) );
7242  }
7243  }
7244  else
7245  {
7246  *violated = TRUE;
7247 
7248  /* only reset constraint age if we are in enforcement */
7249  if( sol == NULL )
7250  {
7251  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7252  }
7253  }
7254  }
7255  else
7256  {
7257  *violated = TRUE;
7258 
7259  /* only reset constraint age if we are in enforcement */
7260  if( sol == NULL )
7261  {
7262  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7263  }
7264  }
7265  }
7266 
7267  /* now regard right hand side */
7268  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7269  {
7270  /* check whether violation is random noise */
7271  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7272  {
7273  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7274  activity - consdata->rhs, maxabs);
7275  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7276 
7277  /* only increase constraint age if we are in enforcement */
7278  if( sol == NULL )
7279  {
7280  SCIP_CALL( SCIPincConsAge(scip, cons) );
7281  }
7282  }
7283  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7284  else if( SCIPisZero(scip, consdata->rhs) )
7285  {
7286  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7287  {
7288  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7289  activity - consdata->rhs, maxabs);
7290  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7291 
7292  /* only increase constraint age if we are in enforcement */
7293  if( sol == NULL )
7294  {
7295  SCIP_CALL( SCIPincConsAge(scip, cons) );
7296  }
7297  }
7298  else
7299  {
7300  *violated = TRUE;
7301 
7302  /* only reset constraint age if we are in enforcement */
7303  if( sol == NULL )
7304  {
7305  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7306  }
7307  }
7308  }
7309  else
7310  {
7311  *violated = TRUE;
7312 
7313  /* only reset constraint age if we are in enforcement */
7314  if( sol == NULL )
7315  {
7316  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7317  }
7318  }
7319  }
7320  }
7321  }
7322  /* check with absolute tolerances */
7323  else if( consdata->checkabsolute &&
7324  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7325  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7326  {
7327  *violated = TRUE;
7328 
7329  /* only reset constraint age if we are in enforcement */
7330  if( sol == NULL )
7331  {
7332  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7333  }
7334  }
7335  else
7336  {
7337  /* only increase constraint age if we are in enforcement */
7338  if( sol == NULL )
7339  {
7340  SCIP_CALL( SCIPincConsAge(scip, cons) );
7341  }
7342  }
7343 
7344  /* update absolute and relative violation of the solution */
7345  if( sol != NULL )
7346  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7347 
7348  return SCIP_OKAY;
7349 }
7350 
7351 /** creates an LP row in a linear constraint data */
7352 static
7354  SCIP* scip, /**< SCIP data structure */
7355  SCIP_CONS* cons /**< linear constraint */
7356  )
7357 {
7358  SCIP_CONSDATA* consdata;
7359 
7360  assert(scip != NULL);
7361  assert(cons != NULL);
7362 
7363  consdata = SCIPconsGetData(cons);
7364  assert(consdata != NULL);
7365  assert(consdata->row == NULL);
7366 
7367  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7369 
7370  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7371 
7372  return SCIP_OKAY;
7373 }
7374 
7375 /** adds linear constraint as cut to the LP */
7376 static
7378  SCIP* scip, /**< SCIP data structure */
7379  SCIP_CONS* cons, /**< linear constraint */
7380  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7381  )
7382 {
7383  SCIP_CONSDATA* consdata;
7384 
7385  assert(scip != NULL);
7386  assert(cons != NULL);
7387 
7388  consdata = SCIPconsGetData(cons);
7389  assert(consdata != NULL);
7390 
7391  if( consdata->row == NULL )
7392  {
7393  /* convert consdata object into LP row */
7394  SCIP_CALL( createRow(scip, cons) );
7395  }
7396  assert(consdata->row != NULL);
7397 
7398  if( consdata->nvars == 0 )
7399  {
7400  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7401  }
7402 
7403  /* insert LP row as cut */
7404  if( !SCIProwIsInLP(consdata->row) )
7405  {
7406  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7407  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7408  /* if presolving is turned off, the row might be trivial */
7409  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7410  {
7411  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7412  }
7413 #ifndef NDEBUG
7414  else
7415  {
7416  int pr;
7417  int cr;
7418  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7419  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7420  assert( pr == 0 || cr == 0 );
7421  }
7422 #endif
7423  }
7424 
7425  return SCIP_OKAY;
7426 }
7427 
7428 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7429 static
7431  SCIP* scip, /**< SCIP data structure */
7432  SCIP_CONS* cons, /**< linear constraint */
7433  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7434  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7435  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7436  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7437  * the ones with non-zero dual value? */
7438  int* ncuts, /**< pointer to add up the number of found cuts */
7439  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7440  )
7441 {
7442  SCIP_CONSDATA* consdata;
7443  SCIP_Bool violated;
7444  int oldncuts;
7445 
7446  assert(scip != NULL);
7447  assert(conshdlrdata != NULL);
7448  assert(cons != NULL);
7449  assert(cutoff != NULL);
7450 
7451  consdata = SCIPconsGetData(cons);
7452  assert(ncuts != NULL);
7453  assert(consdata != NULL);
7454 
7455  oldncuts = *ncuts;
7456  *cutoff = FALSE;
7457 
7458  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7459 
7460  if( violated )
7461  {
7462  /* insert LP row as cut */
7463  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7464  (*ncuts)++;
7465  }
7466  else if( !SCIPconsIsModifiable(cons) && separatecards )
7467  {
7468  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7469  if( !separateall && sol == NULL )
7470  {
7471  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7472  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7473  {
7474  SCIP_Real dualsol;
7475 
7476  dualsol = SCIProwGetDualsol(consdata->row);
7477  if( SCIPisFeasNegative(scip, dualsol) )
7478  {
7479  if( !SCIPisInfinity(scip, consdata->rhs) )
7480  {
7481  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7482  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7483  }
7484  }
7485  else if( SCIPisFeasPositive(scip, dualsol) )
7486  {
7487  if( !SCIPisInfinity(scip, -consdata->lhs) )
7488  {
7489  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7490  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7491  }
7492  }
7493  }
7494  }
7495  else
7496  {
7497  if( !SCIPisInfinity(scip, consdata->rhs) )
7498  {
7499  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7500  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7501  }
7502  if( !SCIPisInfinity(scip, -consdata->lhs) )
7503  {
7504  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7505  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7506  }
7507  }
7508  }
7509 
7510  if( *ncuts > oldncuts )
7511  {
7512  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7513  }
7514 
7515  return SCIP_OKAY;
7516 }
7517 
7518 /** propagation method for linear constraints */
7519 static
7521  SCIP* scip, /**< SCIP data structure */
7522  SCIP_CONS* cons, /**< linear constraint */
7523  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7524  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7525  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7526  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7527  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7528  int* nchgbds /**< pointer to count the total number of tightened bounds */
7529  )
7530 {
7531  SCIP_CONSDATA* consdata;
7532  SCIP_Real minactivity;
7533  SCIP_Real maxactivity;
7534  SCIP_Bool minactisrelax;
7535  SCIP_Bool maxactisrelax;
7536 
7537  assert(scip != NULL);
7538  assert(cons != NULL);
7539  assert(cutoff != NULL);
7540  assert(nchgbds != NULL);
7541 
7542  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7543 
7544  consdata = SCIPconsGetData(cons);
7545  assert(consdata != NULL);
7546 
7547  if( consdata->eventdata == NULL )
7548  {
7549  SCIP_CONSHDLR* conshdlr;
7550  SCIP_CONSHDLRDATA* conshdlrdata;
7551 
7552  conshdlr = SCIPconsGetHdlr(cons);
7553  assert(conshdlr != NULL);
7554 
7555  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7556  assert(conshdlrdata != NULL);
7557 
7558  /* catch bound change events of variables */
7559  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7560  assert(consdata->eventdata != NULL);
7561  }
7562 
7563  *cutoff = FALSE;
7564 
7565  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7566  if( !SCIPconsIsModifiable(cons) )
7567  {
7568  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7569  if( !SCIPinRepropagation(scip) )
7570  {
7571  SCIP_CALL( SCIPincConsAge(scip, cons) );
7572  }
7573 
7574  /* tighten the variable's bounds */
7575  if( tightenbounds )
7576  {
7577  int oldnchgbds;
7578 
7579  oldnchgbds = *nchgbds;
7580 
7581  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7582 
7583  if( *nchgbds > oldnchgbds )
7584  {
7585  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7586  }
7587  }
7588 
7589  /* propagate ranged rows */
7590  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7591  {
7592  int nfixedvars;
7593  int naddconss;
7594  /* cppcheck-suppress unassignedVariable */
7595  int oldnchgbds;
7596 
7597  nfixedvars = 0;
7598  naddconss = 0;
7599  SCIPdebug( oldnchgbds = *nchgbds; )
7600 
7601  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7602 
7603  if( *cutoff )
7604  {
7605  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7606  }
7607  else
7608  {
7609  SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars);
7610  }
7611 
7612  if( nfixedvars > 0 )
7613  *nchgbds += 2*nfixedvars;
7614  }
7615 
7616  /* check constraint for infeasibility and redundancy */
7617  if( !(*cutoff) )
7618  {
7619  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7620 
7621  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7622  {
7623  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7624  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7625 
7626  /* analyze conflict */
7627  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7628 
7629  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7630  *cutoff = TRUE;
7631  }
7632  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7633  {
7634  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7635  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7636 
7637  /* analyze conflict */
7638  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7639 
7640  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7641  *cutoff = TRUE;
7642  }
7643  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7644  {
7645  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7646  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7647 
7648  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7649  if( consdata->nvars > 0 )
7650  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7651  else
7652  SCIP_CALL( SCIPdelCons(scip, cons) );
7653  }
7654  }
7655  }
7656 
7657  return SCIP_OKAY;
7658 }
7659 
7660 
7661 /*
7662  * Presolving methods
7663  */
7664 
7665 /** converts all variables with fixed domain into FIXED variables */
7666 static
7668  SCIP* scip, /**< SCIP data structure */
7669  SCIP_CONS* cons, /**< linear constraint */
7670  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7671  int* nfixedvars /**< pointer to count the total number of fixed variables */
7672  )
7673 {
7674  SCIP_CONSDATA* consdata;
7675  SCIP_VAR* var;
7676  SCIP_VARSTATUS varstatus;
7677  SCIP_Real lb;
7678  SCIP_Real ub;
7679  SCIP_Bool fixed;
7680  SCIP_Bool infeasible;
7681  int v;
7682 
7683  assert(scip != NULL);
7684  assert(cons != NULL);
7685  assert(cutoff != NULL);
7686  assert(nfixedvars != NULL);
7687 
7688  consdata = SCIPconsGetData(cons);
7689  assert(consdata != NULL);
7690 
7691  for( v = 0; v < consdata->nvars; ++v )
7692  {
7693  assert(consdata->vars != NULL);
7694  var = consdata->vars[v];
7695  varstatus = SCIPvarGetStatus(var);
7696 
7697  if( varstatus != SCIP_VARSTATUS_FIXED )
7698  {
7699  lb = SCIPvarGetLbGlobal(var);
7700  ub = SCIPvarGetUbGlobal(var);
7701  if( SCIPisEQ(scip, lb, ub) )
7702  {
7703  SCIP_Real fixval;
7704 
7705  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7706  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7707  SCIPvarGetName(var), lb, ub, fixval);
7708  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7709  if( infeasible )
7710  {
7711  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7712  *cutoff = TRUE;
7713  return SCIP_OKAY;
7714  }
7715  if( fixed )
7716  (*nfixedvars)++;
7717  }
7718  }
7719  }
7720 
7721  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7722 
7723  if( infeasible )
7724  {
7725  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7726  *cutoff = TRUE;
7727  return SCIP_OKAY;
7728  }
7729 
7730  assert(consdata->removedfixings);
7731 
7732  return SCIP_OKAY;
7733 }
7734 
7735 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7736 
7737 /** extracts cliques of the constraint and adds them to SCIP
7738  *
7739  * The following clique extraction mechanism are implemeneted
7740  *
7741  * 1. collect binary variables and sort them in non increasing order, then
7742  *
7743  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7744  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7745  * condition
7746  *
7747  * minactivity + vals[i] + vals[i+1] > rhs
7748  *
7749  * and also add the binary to binary implication also for non-successive variables for which the same argument
7750  * holds
7751  *
7752  * minactivity + vals[i] + vals[j] > rhs
7753  *
7754  * 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
7755  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7756  *
7757  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7758  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7759  * condition
7760  *
7761  * maxactivity + vals[i] + vals[i-1] < lhs
7762  *
7763  * and also add the binary to binary implication also for non-successive variables for which the same argument
7764  * holds
7765  *
7766  * maxactivity + vals[i] + vals[j] < lhs
7767  *
7768  * e.g. you could multiply the above example by -1
7769  *
7770  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7771  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7772  * condition
7773  *
7774  * minactivity - vals[i] - vals[i-1] > rhs
7775  *
7776  * and also add the binary to binary implication also for non-successive variables for which the
7777  * same argument holds
7778  *
7779  * minactivity - vals[i] - vals[j] > rhs
7780  *
7781  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7782  * implication x1 = 0 => x3 = 1
7783  *
7784  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7785  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7786  * condition
7787  *
7788  * maxactivity - vals[i] - vals[i+1] < lhs
7789  *
7790  * and also add the binary to binary implication also for non-successive variables for which the same argument
7791  * holds
7792  *
7793  * maxactivity - vals[i] - vals[j] < lhs
7794  *
7795  * e.g. you could multiply the above example by -1
7796  *
7797  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7798  * as clique, (this part is done at the end of the method)
7799  *
7800  */
7801 static
7803  SCIP* scip, /**< SCIP data structure */
7804  SCIP_CONS* cons, /**< linear constraint */
7805  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7806  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7807  int* nfixedvars, /**< pointer to count number of fixed variables */
7808  int* nchgbds, /**< pointer to count the total number of tightened bounds */
7809  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7810  )
7811 {
7812  SCIP_VAR** vars;
7813  SCIP_Real* vals;
7814  SCIP_CONSDATA* consdata;
7815  SCIP_Bool lhsclique;
7816  SCIP_Bool rhsclique;
7817  SCIP_Bool finitelhs;
7818  SCIP_Bool finiterhs;
7819  SCIP_Bool finiteminact;
7820  SCIP_Bool finitemaxact;
7821  SCIP_Bool finitenegminact;
7822  SCIP_Bool finitenegmaxact;
7823  SCIP_Bool finiteposminact;
7824  SCIP_Bool finiteposmaxact;
7825  SCIP_Bool infeasible;
7826  SCIP_Bool stopped;
7827  int cliquenonzerosadded;
7828  int v;
7829  int i;
7830  int nposcoefs;
7831  int nnegcoefs;
7832  int nvars;
7833 
7834  assert(scip != NULL);
7835  assert(cons != NULL);
7836  assert(nfixedvars != NULL);
7837  assert(nchgbds != NULL);
7838  assert(cutoff != NULL);
7839  assert(!SCIPconsIsDeleted(cons));
7840 
7841  consdata = SCIPconsGetData(cons);
7842  assert(consdata != NULL);
7843 
7844  if( consdata->nvars < 2 )
7845  return SCIP_OKAY;
7846 
7847  /* add implications if posibble
7848  *
7849  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7850  * maximal absolute contribution and also only if this variable would force all other variables to their bound
7851  * corresponding to the global minimal activity of the constraint
7852  */
7853  if( !consdata->implsadded )
7854  {
7855  /* sort variables by variable type */
7856  SCIP_CALL( consdataSort(scip, consdata) );
7857 
7858  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7859  * up front, might change sorting correspondingly
7860  */
7861  /* fast abort if no binaries exist */
7862  if( !SCIPvarIsBinary(consdata->vars[0]) )
7863  return SCIP_OKAY;
7864 
7865  nvars = consdata->nvars;
7866  vars = consdata->vars;
7867  vals = consdata->vals;
7868 
7869  /* recompute activities if needed */
7870  if( !consdata->validactivities )
7871  consdataCalcActivities(scip, consdata);
7872  assert(consdata->validactivities);
7873 
7874  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7875  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7876  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7877  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7878  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7879  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7880  finiteminact = (finitenegminact && finiteposminact);
7881  finitemaxact = (finitenegmaxact && finiteposmaxact);
7882 
7883  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7884  {
7885  SCIP_Real maxabscontrib = -1.0;
7886  SCIP_Bool posval = FALSE;
7887  SCIP_Bool allbinary = TRUE;
7888  int oldnchgbds = *nchgbds;
7889  int nbdchgs = 0;
7890  int nimpls = 0;
7891  int position = -1;
7892 
7893  /* we need a valid minimal/maximal activity to add cliques */
7894  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
7895  {
7896  consdataRecomputeGlbMinactivity(scip, consdata);
7897  assert(consdata->validglbminact);
7898  }
7899 
7900  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
7901  {
7902  consdataRecomputeGlbMaxactivity(scip, consdata);
7903  assert(consdata->validglbmaxact);
7904  }
7905  assert(consdata->validglbminact || consdata->validglbmaxact);
7906 
7907  /* @todo extend this to local/constraint probing */
7908 
7909  /* determine maximal contribution to the activity */
7910  for( v = nvars - 1; v >= 0; --v )
7911  {
7912  if( SCIPvarIsBinary(vars[v]) )
7913  {
7914  if( vals[v] > 0 )
7915  {
7916  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
7917 
7918  if( value > maxabscontrib )
7919  {
7920  maxabscontrib = value;
7921  position = v;
7922  posval = TRUE;
7923  }
7924  }
7925  else
7926  {
7927  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
7928 
7929  value = REALABS(value);
7930 
7931  if( value > maxabscontrib )
7932  {
7933  maxabscontrib = value;
7934  position = v;
7935  posval = FALSE;
7936  }
7937  }
7938  }
7939  else
7940  allbinary = FALSE;
7941  }
7942  assert(0 <= position && position < nvars);
7943 
7944  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
7945  {
7946  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
7947  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7948  * implications
7949  */
7950  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
7951  {
7952  for( v = nvars - 1; v >= 0; --v )
7953  {
7954  /* binary to binary implications will be collected when extrating cliques */
7955  if( !SCIPvarIsBinary(vars[v]) )
7956  {
7957  if( v != position )
7958  {
7959  if( vals[v] > 0 )
7960  {
7961  /* add implications */
7962  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
7963  ++nimpls;
7964  *nchgbds += nbdchgs;
7965  }
7966  else
7967  {
7968  /* add implications */
7969  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
7970  ++nimpls;
7971  *nchgbds += nbdchgs;
7972  }
7973 
7974  if( infeasible )
7975  {
7976  *cutoff = TRUE;
7977  break;
7978  }
7979  }
7980  }
7981  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
7982  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
7983  break;
7984  }
7985  }
7986 
7987  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
7988  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7989  * implications
7990  */
7991  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
7992  {
7993  for( v = nvars - 1; v >= 0; --v )
7994  {
7995  /* binary to binary implications will be collected when extrating cliques */
7996  if( !SCIPvarIsBinary(vars[v]) )
7997  {
7998  if( v != position )
7999  {
8000  if( vals[v] > 0 )
8001  {
8002  /* add implications */
8003  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8004  ++nimpls;
8005  *nchgbds += nbdchgs;
8006  }
8007  else
8008  {
8009  /* add implications */
8010  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8011  ++nimpls;
8012  *nchgbds += nbdchgs;
8013  }
8014 
8015  if( infeasible )
8016  {
8017  *cutoff = TRUE;
8018  break;
8019  }
8020  }
8021  }
8022  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8023  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8024  break;
8025  }
8026  }
8027 
8028  /* did we find some implications */
8029  if( nimpls > 0 )
8030  {
8031  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8032 
8033  if( *cutoff )
8034  return SCIP_OKAY;
8035 
8036  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8037  if( *nchgbds - oldnchgbds > 0 )
8038  {
8039  /* check for fixed variables */
8040  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8041  if( *cutoff )
8042  return SCIP_OKAY;
8043 
8044  /* tighten variable's bounds */
8045  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8046  if( *cutoff )
8047  return SCIP_OKAY;
8048 
8049  /* check for fixed variables */
8050  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8051  if( *cutoff )
8052  return SCIP_OKAY;
8053  }
8054  }
8055  }
8056  }
8057 
8058  consdata->implsadded = TRUE;
8059  }
8060 
8061  /* check if we already added the cliques of this constraint */
8062  if( consdata->cliquesadded )
8063  return SCIP_OKAY;
8064 
8065  consdata->cliquesadded = TRUE;
8066  cliquenonzerosadded = 0;
8067  stopped = FALSE;
8068 
8069  /* sort variables by variable type */
8070  SCIP_CALL( consdataSort(scip, consdata) );
8071 
8072  nvars = consdata->nvars;
8073  vars = consdata->vars;
8074  vals = consdata->vals;
8075 
8076  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8077 
8078  /* recompute activities if needed */
8079  if( !consdata->validactivities )
8080  consdataCalcActivities(scip, consdata);
8081  assert(consdata->validactivities);
8082 
8083  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8084  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8085  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8086  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8087  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8088  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8089  finiteminact = (finitenegminact && finiteposminact);
8090  finitemaxact = (finitenegmaxact && finiteposmaxact);
8091 
8092  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8093  * information
8094  */
8095  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8096  {
8097  SCIP_VAR** binvars;
8098  SCIP_Real* binvarvals;
8099  int nposbinvars = 0;
8100  int nnegbinvars = 0;
8101  int allonebinary = 0;
8102 
8103  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8104  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8105 
8106  /* collect binary variables */
8107  for( i = 0; i < nvars; ++i )
8108  {
8109  if( SCIPvarIsBinary(vars[i]) )
8110  {
8111  assert(!SCIPisZero(scip, vals[i]));
8112 
8113  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8114  ++allonebinary;
8115 
8116  binvars[nposbinvars + nnegbinvars] = vars[i];
8117  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8118 
8119  if( SCIPisPositive(scip, vals[i]) )
8120  ++nposbinvars;
8121  else
8122  ++nnegbinvars;
8123 
8124  assert(nposbinvars + nnegbinvars <= nvars);
8125  }
8126  /* stop searching for binary variables, because the constraint data is sorted */
8127  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8128  break;
8129  }
8130  assert(nposbinvars + nnegbinvars <= nvars);
8131 
8132  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8133  * cliques
8134  */
8135  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8136  {
8137  SCIP_Real threshold;
8138  int oldnchgbds = *nchgbds;
8139  int nbdchgs;
8140  int jstart;
8141  int j;
8142 
8143  /* we need a valid minimal/maximal activity to add cliques */
8144  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8145  {
8146  consdataRecomputeGlbMinactivity(scip, consdata);
8147  assert(consdata->validglbminact);
8148  }
8149 
8150  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8151  {
8152  consdataRecomputeGlbMaxactivity(scip, consdata);
8153  assert(consdata->validglbmaxact);
8154  }
8155  assert(consdata->validglbminact || consdata->validglbmaxact);
8156 
8157  /* sort coefficients non-increasing to be faster in the clique search */
8158  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8159 
8160  /* case a) */
8161  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8162  {
8163  /* compute value that needs to be exceeded */
8164  threshold = consdata->rhs - consdata->glbminactivity;
8165 
8166  i = 0;
8167  j = i + 1;
8168 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8169  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8170  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
8171 #endif
8172  /* check if at least two variables are in a clique */
8173  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
8174  {
8175  ++j;
8176  /* check for extending the clique */
8177  while( j < nposbinvars )
8178  {
8179  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8180  break;
8181  ++j;
8182  }
8183  assert(j >= 2);
8184 
8185  /* add clique with at least two variables */
8186  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, FALSE, &infeasible, &nbdchgs) );
8187 
8188  if( infeasible )
8189  *cutoff = TRUE;
8190 
8191  *nchgbds += nbdchgs;
8192 
8193  cliquenonzerosadded += j;
8194  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8195  stopped = TRUE;
8196 
8197  /* exchange the last variable in the clique if possible and add all new ones */
8198  if( !stopped && !(*cutoff) && j < nposbinvars )
8199  {
8200  SCIP_VAR** clqvars;
8201  int lastfit = j - 2;
8202  assert(lastfit >= i);
8203 
8204  /* copy all 'main'-clique variables */
8205  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8206 
8207  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8208  while( lastfit >= i && j < nposbinvars )
8209  {
8210  /* check if two variables are in a clique */
8211  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8212  {
8213  clqvars[lastfit + 1] = binvars[j];
8214 
8215  /* add clique with at least two variables */
8216  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8217 
8218  if( infeasible )
8219  {
8220  *cutoff = TRUE;
8221  break;
8222  }
8223 
8224  *nchgbds += nbdchgs;
8225 
8226  cliquenonzerosadded += (lastfit - i + 2);
8227  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8228  {
8229  stopped = TRUE;
8230  break;
8231  }
8232 
8233  ++j;
8234  }
8235  else
8236  --lastfit;
8237  }
8238 
8239  SCIPfreeBufferArray(scip, &clqvars);
8240  }
8241  }
8242  }
8243 
8244  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8245  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8246  {
8247  /* check for fixed variables */
8248  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8249 
8250  if( !*cutoff )
8251  {
8252  /* tighten variable's bounds */
8253  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8254 
8255  if( !*cutoff )
8256  {
8257  /* check for fixed variables */
8258  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8259 
8260  if( !*cutoff )
8261  {
8262  /* sort variables by variable type */
8263  SCIP_CALL( consdataSort(scip, consdata) );
8264 
8265  /* recompute activities if needed */
8266  if( !consdata->validactivities )
8267  consdataCalcActivities(scip, consdata);
8268  assert(consdata->validactivities);
8269 
8270  nvars = consdata->nvars;
8271  vars = consdata->vars;
8272  vals = consdata->vals;
8273  nposbinvars = 0;
8274  nnegbinvars = 0;
8275  allonebinary = 0;
8276 
8277  /* update binary variables */
8278  for( i = 0; i < nvars; ++i )
8279  {
8280  if( SCIPvarIsBinary(vars[i]) )
8281  {
8282  assert(!SCIPisZero(scip, vals[i]));
8283 
8284  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8285  ++allonebinary;
8286 
8287  binvars[nposbinvars + nnegbinvars] = vars[i];
8288  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8289 
8290  if( SCIPisPositive(scip, vals[i]) )
8291  ++nposbinvars;
8292  else
8293  ++nnegbinvars;
8294 
8295  assert(nposbinvars + nnegbinvars <= nvars);
8296  }
8297  /* stop searching for binary variables, because the constraint data is sorted */
8298  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8299  break;
8300  }
8301  assert(nposbinvars + nnegbinvars <= nvars);
8302  }
8303  }
8304  }
8305 
8306  oldnchgbds = *nchgbds;
8307  }
8308 
8309  /* case b) */
8310  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8311  {
8312  /* compute value that needs to be deceeded */
8313  threshold = consdata->lhs - consdata->glbmaxactivity;
8314 
8315  i = nposbinvars + nnegbinvars - 1;
8316  j = i - 1;
8317 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8318  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8319  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8320 #endif
8321  /* check if two variables are in a clique */
8322  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8323  {
8324  --j;
8325  /* check for extending the clique */
8326  while( j >= nposbinvars )
8327  {
8328  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8329  break;
8330  --j;
8331  }
8332  jstart = j;
8333 
8334  assert(i - j >= 2);
8335  /* add clique with at least two variables */
8336  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8337 
8338  if( infeasible )
8339  *cutoff = TRUE;
8340 
8341  *nchgbds += nbdchgs;
8342 
8343  cliquenonzerosadded += (i - j);
8344  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8345  stopped = TRUE;
8346 
8347  /* exchange the last variable in the clique if possible and add all new ones */
8348  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8349  {
8350  SCIP_VAR** clqvars;
8351  int lastfit = jstart + 1;
8352  assert(lastfit < i);
8353 
8354  /* copy all 'main'-clique variables */
8355  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8356  ++lastfit;
8357 
8358  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8359  while( lastfit <= i && j >= nposbinvars )
8360  {
8361  /* check if two variables are in a clique */
8362  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8363  {
8364  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8365  clqvars[lastfit - jstart - 2] = binvars[j];
8366 
8367  assert(i - lastfit + 2 >= 2);
8368  /* add clique with at least two variables */
8369  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8370 
8371  if( infeasible )
8372  {
8373  *cutoff = TRUE;
8374  break;
8375  }
8376 
8377  *nchgbds += nbdchgs;
8378 
8379  cliquenonzerosadded += (i - lastfit + 2);
8380  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8381  {
8382  stopped = TRUE;
8383  break;
8384  }
8385 
8386  --j;
8387  }
8388  else
8389  ++lastfit;
8390  }
8391 
8392  SCIPfreeBufferArray(scip, &clqvars);
8393  }
8394  }
8395  }
8396 
8397  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8398  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8399  {
8400  /* check for fixed variables */
8401  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8402 
8403  if( !*cutoff )
8404  {
8405  /* tighten variable's bounds */
8406  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8407 
8408  if( !*cutoff )
8409  {
8410  /* check for fixed variables */
8411  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8412 
8413  if( !*cutoff )
8414  {
8415  /* sort variables by variable type */
8416  SCIP_CALL( consdataSort(scip, consdata) );
8417 
8418  /* recompute activities if needed */
8419  if( !consdata->validactivities )
8420  consdataCalcActivities(scip, consdata);
8421  assert(consdata->validactivities);
8422 
8423  nvars = consdata->nvars;
8424  vars = consdata->vars;
8425  vals = consdata->vals;
8426  nposbinvars = 0;
8427  nnegbinvars = 0;
8428  allonebinary = 0;
8429 
8430  /* update binary variables */
8431  for( i = 0; i < nvars; ++i )
8432  {
8433  if( SCIPvarIsBinary(vars[i]) )
8434  {
8435  assert(!SCIPisZero(scip, vals[i]));
8436 
8437  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8438  ++allonebinary;
8439 
8440  binvars[nposbinvars + nnegbinvars] = vars[i];
8441  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8442 
8443  if( SCIPisPositive(scip, vals[i]) )
8444  ++nposbinvars;
8445  else
8446  ++nnegbinvars;
8447 
8448  assert(nposbinvars + nnegbinvars <= nvars);
8449  }
8450  /* stop searching for binary variables, because the constraint data is sorted */
8451  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8452  break;
8453  }
8454  assert(nposbinvars + nnegbinvars <= nvars);
8455  }
8456  }
8457  }
8458 
8459  oldnchgbds = *nchgbds;
8460  }
8461 
8462  /* case c) */
8463  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8464  {
8465  SCIP_Bool* values;
8466 
8467  /* initialize clique values array for adding a negated clique */
8468  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8469  BMSclearMemoryArray(values, nnegbinvars);
8470 
8471  /* compute value that needs to be exceeded */
8472  threshold = consdata->rhs - consdata->glbminactivity;
8473 
8474  i = nposbinvars + nnegbinvars - 1;
8475  j = i - 1;
8476 
8477 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8478  /* check if the variable should not have already been fixed to one */
8479  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8480 #endif
8481 
8482  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8483  {
8484  --j;
8485  /* check for extending the clique */
8486  while( j >= nposbinvars )
8487  {
8488  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8489  break;
8490  --j;
8491  }
8492  jstart = j;
8493 
8494  assert(i - j >= 2);
8495  /* add negated clique with at least two variables */
8496  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8497 
8498  if( infeasible )
8499  *cutoff = TRUE;
8500 
8501  *nchgbds += nbdchgs;
8502 
8503  cliquenonzerosadded += (i - j);
8504  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8505  stopped = TRUE;
8506 
8507  /* exchange the last variable in the clique if possible and add all new ones */
8508  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8509  {
8510  SCIP_VAR** clqvars;
8511  int lastfit = j + 1;
8512  assert(lastfit < i);
8513 
8514  /* copy all 'main'-clique variables */
8515  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8516  ++lastfit;
8517 
8518  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8519  while( lastfit <= i && j >= nposbinvars )
8520  {
8521  /* check if two variables are in a negated clique */
8522  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8523  {
8524  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8525  clqvars[lastfit - jstart - 2] = binvars[j];
8526 
8527  assert(i - lastfit + 2 >= 2);
8528  /* add clique with at least two variables */
8529  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8530 
8531  if( infeasible )
8532  {
8533  *cutoff = TRUE;
8534  break;
8535  }
8536 
8537  *nchgbds += nbdchgs;
8538 
8539  cliquenonzerosadded += (i - lastfit + 2);
8540  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8541  {
8542  stopped = TRUE;
8543  break;
8544  }
8545 
8546  --j;
8547  }
8548  else
8549  ++lastfit;
8550  }
8551 
8552  SCIPfreeBufferArray(scip, &clqvars);
8553  }
8554  }
8555 
8556  SCIPfreeBufferArray(scip, &values);
8557  }
8558 
8559  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8560  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8561  {
8562  /* check for fixed variables */
8563  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8564 
8565  if( !*cutoff )
8566  {
8567  /* tighten variable's bounds */
8568  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8569 
8570  if( !*cutoff )
8571  {
8572  /* check for fixed variables */
8573  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8574 
8575  if( !*cutoff )
8576  {
8577  /* sort variables by variable type */
8578  SCIP_CALL( consdataSort(scip, consdata) );
8579 
8580  /* recompute activities if needed */
8581  if( !consdata->validactivities )
8582  consdataCalcActivities(scip, consdata);
8583  assert(consdata->validactivities);
8584 
8585  nvars = consdata->nvars;
8586  vars = consdata->vars;
8587  vals = consdata->vals;
8588  nposbinvars = 0;
8589  nnegbinvars = 0;
8590  allonebinary = 0;
8591 
8592  /* update binary variables */
8593  for( i = 0; i < nvars; ++i )
8594  {
8595  if( SCIPvarIsBinary(vars[i]) )
8596  {
8597  assert(!SCIPisZero(scip, vals[i]));
8598 
8599  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8600  ++allonebinary;
8601 
8602  binvars[nposbinvars + nnegbinvars] = vars[i];
8603  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8604 
8605  if( SCIPisPositive(scip, vals[i]) )
8606  ++nposbinvars;
8607  else
8608  ++nnegbinvars;
8609 
8610  assert(nposbinvars + nnegbinvars <= nvars);
8611  }
8612  /* stop searching for binary variables, because the constraint data is sorted */
8613  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8614  break;
8615  }
8616  assert(nposbinvars + nnegbinvars <= nvars);
8617  }
8618  }
8619  }
8620  }
8621 
8622  /* case d) */
8623  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8624  {
8625  SCIP_Bool* values;
8626 
8627  /* initialize clique values array for adding a negated clique */
8628  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8629  BMSclearMemoryArray(values, nposbinvars);
8630 
8631  /* compute value that needs to be exceeded */
8632  threshold = consdata->lhs - consdata->glbmaxactivity;
8633 
8634  i = 0;
8635  j = i + 1;
8636 
8637 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8638  /* check if the variable should not have already been fixed to one */
8639  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
8640 #endif
8641 
8642  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8643  {
8644  ++j;
8645  /* check for extending the clique */
8646  while( j < nposbinvars )
8647  {
8648  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8649  break;
8650  ++j;
8651  }
8652  assert(j >= 2);
8653 
8654  /* add negated clique with at least two variables */
8655  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, FALSE, &infeasible, &nbdchgs) );
8656 
8657  if( infeasible )
8658  *cutoff = TRUE;
8659 
8660  *nchgbds += nbdchgs;
8661 
8662  cliquenonzerosadded += j;
8663  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8664  stopped = TRUE;
8665 
8666  /* exchange the last variable in the clique if possible and add all new ones */
8667  if( !stopped && !(*cutoff) && j < nposbinvars )
8668  {
8669  SCIP_VAR** clqvars;
8670  int lastfit = j - 2;
8671  assert(lastfit >= i);
8672 
8673  /* copy all 'main'-clique variables */
8674  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8675 
8676  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8677  while( lastfit >= i && j < nposbinvars )
8678  {
8679  /* check if two variables are in a negated clique */
8680  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8681  {
8682  clqvars[lastfit + 1] = binvars[j];
8683 
8684  /* add clique with at least two variables */
8685  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8686 
8687  if( infeasible )
8688  {
8689  *cutoff = TRUE;
8690  break;
8691  }
8692 
8693  *nchgbds += nbdchgs;
8694 
8695  cliquenonzerosadded += (lastfit - i + 2);
8696  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8697  break;
8698 
8699  ++j;
8700  }
8701  else
8702  --lastfit;
8703  }
8704 
8705  SCIPfreeBufferArray(scip, &clqvars);
8706  }
8707  }
8708 
8709  SCIPfreeBufferArray(scip, &values);
8710  }
8711  }
8712 
8713  SCIPfreeBufferArray(scip, &binvarvals);
8714  SCIPfreeBufferArray(scip, &binvars);
8715 
8716  if( *cutoff )
8717  return SCIP_OKAY;
8718  }
8719 
8720  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8721 
8722  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8723  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8724  */
8725  nposcoefs = 0;
8726  nnegcoefs = 0;
8727  for( i = 0; i < nvars; ++i )
8728  {
8729  if( !SCIPvarIsBinary(vars[i]) )
8730  return SCIP_OKAY;
8731  else if( SCIPisEQ(scip, vals[i], +1.0) )
8732  nposcoefs++;
8733  else if( SCIPisEQ(scip, vals[i], -1.0) )
8734  nnegcoefs++;
8735  else
8736  return SCIP_OKAY;
8737  }
8738 
8739  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8740  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8741 
8742  if( lhsclique || rhsclique )
8743  {
8744  SCIP_Bool* values;
8745  int nbdchgs;
8746 
8747  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8748  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8749  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8750 
8751  for( i = 0; i < nvars; ++i )
8752  values[i] = (rhsclique == (vals[i] > 0.0));
8753 
8754  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8755 
8756  if( infeasible )
8757  *cutoff = TRUE;
8758 
8759  *nchgbds += nbdchgs;
8760  SCIPfreeBufferArray(scip, &values);
8761  }
8762 
8763  return SCIP_OKAY;
8764 }
8765 
8766 /** tightens left and right hand side of constraint due to integrality */
8767 static
8769  SCIP* scip, /**< SCIP data structure */
8770  SCIP_CONS* cons, /**< linear constraint */
8771  int* nchgsides /**< pointer to count number of side changes */
8772  )
8773 {
8774  SCIP_CONSDATA* consdata;
8775  SCIP_Bool integral;
8776  int i;
8777 
8778  assert(scip != NULL);
8779  assert(cons != NULL);
8780  assert(nchgsides != NULL);
8781 
8782  consdata = SCIPconsGetData(cons);
8783  assert(consdata != NULL);
8784 
8785  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8786  {
8787  integral = TRUE;
8788  for( i = 0; i < consdata->nvars && integral; ++i )
8789  {
8790  integral = SCIPisIntegral(scip, consdata->vals[i])
8791  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8792  }
8793  if( integral )
8794  {
8795  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8796  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8797  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8798  {
8799  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
8800  if( !consdata->upgraded )
8801  (*nchgsides)++;
8802  }
8803  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8804  {
8805  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
8806  if( !consdata->upgraded )
8807  (*nchgsides)++;
8808  }
8809  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8810  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8811  }
8812  }
8813 
8814  return SCIP_OKAY;
8815 }
8816 
8817 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8818  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8819  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8820  * (i) ai >= 0:
8821  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8822  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8823  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8824  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8825  * - change coefficients:
8826  * ai' := max(lhs - minact, maxact - rhs)
8827  * lhs' := lhs - (ai - ai')*li
8828  * rhs' := rhs - (ai - ai')*ui
8829  * (ii) ai < 0:
8830  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8831  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8832  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8833  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8834  * - change coefficients:
8835  * ai' := min(rhs - maxact, minact - lhs)
8836  * lhs' := lhs - (ai - ai')*ui
8837  * rhs' := rhs - (ai - ai')*li
8838  *
8839  * We further try to remove redundant variable from the constraint;
8840  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
8841  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8842  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
8843  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
8844  * 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
8845  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
8846  *
8847  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8848  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8849  */
8850 static
8852  SCIP* scip, /**< SCIP data structure */
8853  SCIP_CONS* cons, /**< linear constraint */
8854  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8855  int* nchgsides /**< pointer to count number of side changes */
8856  )
8857 {
8858  SCIP_CONSDATA* consdata;
8859  SCIP_VAR* var;
8860  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
8861  * activity, ignoring the coefficients contributing with infinite value */
8862  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
8863  * activity, ignoring the coefficients contributing with infinite value */
8864  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
8865  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
8866  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
8867  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
8868  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
8869  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
8870  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
8871  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
8872  SCIP_Real val;
8873  SCIP_Real newval;
8874  SCIP_Real newlhs;
8875  SCIP_Real newrhs;
8876  SCIP_Real lb;
8877  SCIP_Real ub;
8878  int i;
8879 
8880  assert(scip != NULL);
8881  assert(cons != NULL);
8882  assert(nchgcoefs != NULL);
8883  assert(nchgsides != NULL);
8884 
8885  consdata = SCIPconsGetData(cons);
8886  assert(consdata != NULL);
8887 
8888  /* @todo Is this still needed with automatic recomputation of activities? */
8889  /* if the maximal coefficient is too large, recompute the activities */
8890  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
8891  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
8892  {
8893  consdataRecomputeMinactivity(scip, consdata);
8894  consdataRecomputeMaxactivity(scip, consdata);
8895  }
8896 
8897  /* get the minimal and maximal activity of the constraint */
8898  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8899 
8900  minleftactivity = 0.0;
8901  maxleftactivity = 0.0;
8902 
8903  /* try to tighten each coefficient */
8904  i = 0;
8905  while( i < consdata->nvars )
8906  {
8907  var = consdata->vars[i];
8908 
8909  /* get coefficient and variable's bounds */
8910  lb = SCIPvarGetLbLocal(var);
8911  ub = SCIPvarGetUbLocal(var);
8912  val = consdata->vals[i];
8913  assert(!SCIPisZero(scip, val));
8914 
8915  /* check sign of coefficient */
8916  if( val >= 0.0 )
8917  {
8918  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
8920  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
8921  {
8922  /* change coefficients:
8923  * ai' := max(lhs - minact, maxact - rhs)
8924  * lhs' := lhs - (ai - ai')*li
8925  * rhs' := rhs - (ai - ai')*ui
8926  */
8927 
8928  lval = consdata->lhs - minactivity;
8929  rval = maxactivity - consdata->rhs;
8930 
8931  /* Try to avoid cancellation, if there are only two variables */
8932  if( consdata->nvars == 2 )
8933  {
8934  SCIP_Real otherval;
8935  otherval = consdata->vals[1-i];
8936 
8937  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
8938  {
8939  lval = consdata->lhs - val*lb;
8940  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
8941  }
8942 
8943  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
8944  {
8945  rval = val*ub - consdata->rhs;
8946  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
8947  }
8948  }
8949 
8950  newval = MAX(lval, rval);
8951  assert(SCIPisSumRelLE(scip, newval, val));
8952 
8953  /* Try to avoid cancellation in computation of lhs/rhs */
8954  newlhs = consdata->lhs - val * lb;
8955  newlhs += newval * lb;
8956  newrhs = consdata->rhs - val * ub;
8957  newrhs += newval * ub;
8958 
8959  if( !SCIPisSumRelEQ(scip, newval, val) )
8960  {
8961  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
8962  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
8963  minactivity, maxactivity, consdata->lhs, consdata->rhs);
8964 
8965  /* update the coefficient and the activity bounds */
8966  if( SCIPisZero(scip, newval) )
8967  {
8968  SCIP_CALL( delCoefPos(scip, cons, i) );
8969  i--;
8970  }
8971  else
8972  {
8973  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
8974  }
8975  (*nchgcoefs)++;
8976 
8977  /* get the new minimal and maximal activity of the constraint */
8978  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8979 
8980  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
8981  {
8982  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
8983 
8984  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8985  (*nchgsides)++;
8986  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
8987  }
8988 
8989  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
8990  {
8991  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
8992 
8993  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8994  (*nchgsides)++;
8995  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
8996  }
8997  }
8998  }
8999  else
9000  {
9001  if( !SCIPisInfinity(scip, -minleftactivity) )
9002  {
9003  assert(!SCIPisInfinity(scip, val));
9004  assert(!SCIPisInfinity(scip, lb));
9005  if( SCIPisInfinity(scip, -lb) )
9006  minleftactivity = -SCIPinfinity(scip);
9007  else
9008  minleftactivity += val * lb;
9009  }
9010 
9011  if( !SCIPisInfinity(scip, maxleftactivity) )
9012  {
9013  assert(!SCIPisInfinity(scip, val));
9014  assert(!SCIPisInfinity(scip, -ub));
9015  if( SCIPisInfinity(scip,ub) )
9016  maxleftactivity = SCIPinfinity(scip);
9017  else
9018  maxleftactivity += val * ub;
9019  }
9020  }
9021  }
9022  else
9023  {
9024  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9026  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9027  {
9028  /* change coefficients:
9029  * ai' := min(rhs - maxact, minact - lhs)
9030  * lhs' := lhs - (ai - ai')*ui
9031  * rhs' := rhs - (ai - ai')*li
9032  */
9033 
9034  lval = minactivity - consdata->lhs;
9035  rval = consdata->rhs - maxactivity;
9036 
9037  /* Try to avoid cancellation, if there are only two variables */
9038  if( consdata->nvars == 2 )
9039  {
9040  SCIP_Real otherval;
9041  otherval = consdata->vals[1-i];
9042 
9043  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9044  {
9045  lval = val*ub - consdata->lhs;
9046  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9047  }
9048 
9049  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9050  {
9051  rval = consdata->rhs - val*lb;
9052  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9053  }
9054  }
9055 
9056  newval = MIN(lval, rval);
9057  assert(SCIPisSumRelGE(scip, newval, val));
9058 
9059  /* Try to avoid cancellation in computation of lhs/rhs */
9060  newlhs = consdata->lhs - val * ub;
9061  newlhs += newval * ub;
9062  newrhs = consdata->rhs - val * lb;
9063  newrhs += newval * lb;
9064 
9065  if( !SCIPisSumRelEQ(scip, newval, val) )
9066  {
9067  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9068  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9069  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9070 
9071  /* update the coefficient and the activity bounds */
9072  if( SCIPisZero(scip, newval) )
9073  {
9074  SCIP_CALL( delCoefPos(scip, cons, i) );
9075  i--;
9076  }
9077  else
9078  {
9079  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9080  }
9081  (*nchgcoefs)++;
9082 
9083  /* get the new minimal and maximal activity of the constraint */
9084  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9085 
9086  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9087  {
9088  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9089 
9090  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9091  (*nchgsides)++;
9092  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9093  }
9094 
9095  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9096  {
9097  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9098 
9099  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9100  (*nchgsides)++;
9101  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9102  }
9103  }
9104  }
9105  else
9106  {
9107  if( !SCIPisInfinity(scip, -minleftactivity) )
9108  {
9109  assert(!SCIPisInfinity(scip, -val));
9110  assert(!SCIPisInfinity(scip, -ub));
9111  if( SCIPisInfinity(scip, ub) )
9112  minleftactivity = -SCIPinfinity(scip);
9113  else
9114  minleftactivity += val * ub;
9115  }
9116 
9117  if( !SCIPisInfinity(scip, maxleftactivity) )
9118  {
9119  assert(!SCIPisInfinity(scip, -val));
9120  assert(!SCIPisInfinity(scip, lb));
9121  if( SCIPisInfinity(scip, -lb) )
9122  maxleftactivity = SCIPinfinity(scip);
9123  else
9124  maxleftactivity += val * lb;
9125  }
9126  }
9127  }
9128  ++i;
9129  }
9130 
9131  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9132  minleftactivity, consdata->rhs);
9133  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9134  maxleftactivity, consdata->lhs);
9135 
9136  /* minleft == \infty ==> minactivity == \infty */
9137  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9138  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9139 
9140  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9141  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9142  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9143  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9144  */
9145  assert(!SCIPisInfinity(scip, minactivity));
9146  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9147  return SCIP_OKAY;
9148 
9149  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9150  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9151  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9152  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9153  */
9154  assert(!SCIPisInfinity(scip, -maxactivity));
9155  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9156  return SCIP_OKAY;
9157 
9158  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9159  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9160  */
9161  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9162  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9163 
9164  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9165  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9166  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9167  * they can be removed from the constraint.
9168  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9169  */
9170  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9171  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9172  {
9173  SCIP_Real minleftactivitypart;
9174  SCIP_Real maxleftactivitypart;
9175 
9176  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9177 
9178  /* try to remove redundant variables from constraint */
9179  i = 0;
9180  while( i < consdata->nvars )
9181  {
9182  var = consdata->vars[i];
9183  minleftactivitypart = 0.0;
9184  maxleftactivitypart = 0.0;
9185  lb = SCIPvarGetLbLocal(var);
9186  ub = SCIPvarGetUbLocal(var);
9187 
9188  /* get coefficient and variable's bounds */
9189  val = consdata->vals[i];
9190  assert(!SCIPisZero(scip, val));
9191 
9192  /* check sign of coefficient */
9193  if( val >= 0.0 )
9194  {
9195  /* negation of condition above in case of positive val */
9196  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9197  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9198  {
9199  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9200  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9201  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9202  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9203 
9204  minleftactivitypart = val * lb;
9205  maxleftactivitypart = val * ub;
9206 
9207  SCIP_CALL( delCoefPos(scip, cons, i) );
9208  i--;
9209 
9210  /* get the new minimal and maximal activity of the constraint */
9211  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9212 
9213  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9214  * huge contributions
9215  */
9216  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9217  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9218  }
9219  }
9220  else
9221  {
9222  /* negation of condition above in case of negative val */
9223  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9224  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9225  {
9226  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9227  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9228 
9229  minleftactivitypart = val * ub;
9230  maxleftactivitypart = val * lb;
9231 
9232  SCIP_CALL( delCoefPos(scip, cons, i) );
9233  i--;
9234 
9235  /* get the new minimal and maximal activity of the constraint */
9236  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9237 
9238  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9239  * huge contributions
9240  */
9241  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9242  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9243  }
9244  }
9245 
9246  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9247  * redundant variables could get deleted,
9248  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9249  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9250  * we would also delete y2 and as a result we would have gotten infeasibility */
9251  /* adjust lhs and right hand side */
9252  newlhs = consdata->lhs - minleftactivitypart;
9253  newrhs = consdata->rhs - maxleftactivitypart;
9254 
9255  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9256  {
9257  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9258  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9259  ++(*nchgsides);
9260  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9261  }
9262  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9263  {
9264  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9265  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9266  ++(*nchgsides);
9267  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9268  }
9269  ++i;
9270  }
9271  }
9272 
9273  return SCIP_OKAY;
9274 }
9275 
9276 /* processes equality with only one variable by fixing the variable and deleting the constraint */
9277 static
9279  SCIP* scip, /**< SCIP data structure */
9280  SCIP_CONS* cons, /**< linear constraint */
9281  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9282  int* nfixedvars, /**< pointer to count number of fixed variables */
9283  int* ndelconss /**< pointer to count number of deleted constraints */
9284  )
9285 {
9286  SCIP_CONSDATA* consdata;
9287  SCIP_VAR* var;
9288  SCIP_Real val;
9289  SCIP_Real fixval;
9290  SCIP_Bool infeasible;
9291  SCIP_Bool fixed;
9292 
9293  assert(scip != NULL);
9294  assert(cons != NULL);
9295  assert(cutoff != NULL);
9296  assert(nfixedvars != NULL);
9297  assert(ndelconss != NULL);
9298 
9299  consdata = SCIPconsGetData(cons);
9300  assert(consdata != NULL);
9301  assert(consdata->nvars == 1);
9302  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9303 
9304  /* calculate the value to fix the variable to */
9305  var = consdata->vars[0];
9306  val = consdata->vals[0];
9307  assert(!SCIPisZero(scip, val));
9308  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9309  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9310  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9311  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9312 
9313  /* fix variable */
9314  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9315  if( infeasible )
9316  {
9317  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9318  *cutoff = TRUE;
9319  return SCIP_OKAY;
9320  }
9321  if( fixed )
9322  (*nfixedvars)++;
9323 
9324  /* disable constraint */
9325  SCIP_CALL( SCIPdelCons(scip, cons) );
9326  if( !consdata->upgraded )
9327  (*ndelconss)++;
9328 
9329  return SCIP_OKAY;
9330 }
9331 
9332 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9333 static
9335  SCIP* scip, /**< SCIP data structure */
9336  SCIP_CONS* cons, /**< linear constraint */
9337  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9338  int* naggrvars, /**< pointer to count number of aggregated variables */
9339  int* ndelconss /**< pointer to count number of deleted constraints */
9340  )
9341 {
9342  SCIP_CONSDATA* consdata;
9343  SCIP_Bool infeasible;
9344  SCIP_Bool redundant;
9345  SCIP_Bool aggregated;
9346 
9347  assert(scip != NULL);
9348  assert(cons != NULL);
9349  assert(cutoff != NULL);
9350  assert(naggrvars != NULL);
9351  assert(ndelconss != NULL);
9352 
9353  consdata = SCIPconsGetData(cons);
9354  assert(consdata != NULL);
9355  assert(consdata->nvars == 2);
9356  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9357 
9358  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9359  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9360  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9361 
9362  /* aggregate the equality */
9363  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9364  consdata->rhs, &infeasible, &redundant, &aggregated) );
9365 
9366  /* check for infeasibility of aggregation */
9367  if( infeasible )
9368  {
9369  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9370  *cutoff = TRUE;
9371  return SCIP_OKAY;
9372  }
9373 
9374  /* count the aggregation */
9375  if( aggregated )
9376  (*naggrvars)++;
9377 
9378  /* delete the constraint, if it is redundant */
9379  if( redundant )
9380  {
9381  SCIP_CALL( SCIPdelCons(scip, cons) );
9382 
9383  if( !consdata->upgraded )
9384  (*ndelconss)++;
9385  }
9386 
9387  return SCIP_OKAY;
9388 }
9389 
9390 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9391 static
9393  SCIP* scip, /**< SCIP data structure */
9394  SCIP_CONSDATA* consdata, /**< linear constraint data */
9395  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9396  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9397  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9398  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9399  )
9400 {
9401  SCIP_Real slackvarlb;
9402  SCIP_Real slackvarub;
9403 
9404  assert(scip != NULL);
9405  assert(consdata != NULL);
9406  assert(newlhs != NULL);
9407  assert(newrhs != NULL);
9408  assert(!SCIPisInfinity(scip, -consdata->lhs));
9409  assert(!SCIPisInfinity(scip, consdata->rhs));
9410 
9411  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9412  slackvarub = SCIPvarGetUbGlobal(slackvar);
9413  if( slackcoef > 0.0 )
9414  {
9415  if( SCIPisInfinity(scip, -slackvarlb) )
9416  *newrhs = SCIPinfinity(scip);
9417  else
9418  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9419  if( SCIPisInfinity(scip, slackvarub) )
9420  *newlhs = -SCIPinfinity(scip);
9421  else
9422  *newlhs = consdata->lhs - slackcoef * slackvarub;
9423  }
9424  else
9425  {
9426  if( SCIPisInfinity(scip, -slackvarlb) )
9427  *newlhs = -SCIPinfinity(scip);
9428  else
9429  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9430  if( SCIPisInfinity(scip, slackvarub) )
9431  *newrhs = SCIPinfinity(scip);
9432  else
9433  *newrhs = consdata->lhs - slackcoef * slackvarub;
9434  }
9435  assert(SCIPisLE(scip, *newlhs, *newrhs));
9436 }
9437 
9438 #define MAXMULTIAGGRQUOTIENT 1e+03
9439 
9440 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9441  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9442  * is implicitly integral by this constraint
9443  *
9444  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9445  * can help.
9446  */
9447 static
9449  SCIP* scip, /**< SCIP data structure */
9450  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9451  SCIP_CONS* cons, /**< linear constraint */
9452  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9453  int* naggrvars, /**< pointer to count number of aggregated variables */
9454  int* ndelconss /**< pointer to count number of deleted constraints */
9455  )
9456 {
9457  SCIP_CONSDATA* consdata;
9458  SCIP_VAR** vars;
9459  SCIP_Real* vals;
9460  SCIP_VARTYPE bestslacktype;
9461  SCIP_VARTYPE slacktype;
9462  SCIP_Real lhs;
9463  SCIP_Real rhs;
9464  SCIP_Real bestslackdomrng;
9465  SCIP_Real minabsval;
9466  SCIP_Real maxabsval;
9467  SCIP_Bool bestremovescons;
9468  SCIP_Bool coefszeroone;
9469  SCIP_Bool coefsintegral;
9470  SCIP_Bool varsintegral;
9471  SCIP_Bool infeasible;
9472  SCIP_Bool samevar;
9473  int supinf; /* counter for infinite contributions to the supremum of a possible
9474  * multi-aggregation
9475  */
9476  int infinf; /* counter for infinite contributions to the infimum of a possible
9477  * multi-aggregation
9478  */
9479  int maxnlocksstay;
9480  int maxnlocksremove;
9481  int bestslackpos;
9482  int bestnlocks;
9483  int ncontvars;
9484  int contvarpos;
9485  int nintvars;
9486  int nimplvars;
9487  int intvarpos;
9488  int v;
9489 
9490  assert(scip != NULL);
9491  assert(cons != NULL);
9492  assert(cutoff != NULL);
9493  assert(naggrvars != NULL);
9494 
9495  consdata = SCIPconsGetData(cons);
9496  assert(consdata != NULL);
9497  assert(consdata->nvars > 2);
9498  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9499 
9500  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9501 
9502  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9503  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9504  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9505  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9506  */
9507  lhs = consdata->lhs;
9508  rhs = consdata->rhs;
9509  maxnlocksstay = 0;
9510  if( consdata->nvars == 3 )
9511  {
9512  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9513  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9514  */
9515  maxnlocksremove = 3;
9516  }
9517  else if( consdata->nvars == 4 )
9518  {
9519  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9520  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9521  */
9522  maxnlocksremove = 2;
9523  }
9524  else
9525  {
9526  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9527  maxnlocksremove = 1;
9528  }
9529 
9530  /* the locks on this constraint can be ignored */
9531  if( SCIPconsIsChecked(cons) )
9532  {
9533  if( !SCIPisInfinity(scip, -lhs) )
9534  {
9535  maxnlocksstay++;
9536  maxnlocksremove++;
9537  }
9538  if( !SCIPisInfinity(scip, rhs) )
9539  {
9540  maxnlocksstay++;
9541  maxnlocksremove++;
9542  }
9543  }
9544 
9545  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9546  vars = consdata->vars;
9547  vals = consdata->vals;
9548  bestslackpos = -1;
9549  bestslacktype = SCIP_VARTYPE_BINARY;
9550  bestnlocks = INT_MAX;
9551  bestremovescons = FALSE;
9552  bestslackdomrng = 0.0;
9553  coefszeroone = TRUE;
9554  coefsintegral = TRUE;
9555  varsintegral = TRUE;
9556  ncontvars = 0;
9557  contvarpos = -1;
9558  nintvars = 0;
9559  nimplvars = 0;
9560  intvarpos = -1;
9561  minabsval = SCIPinfinity(scip);
9562  maxabsval = -1.0;
9563  for( v = 0; v < consdata->nvars; ++v )
9564  {
9565  SCIP_VAR* var;
9566  SCIP_Real val;
9567  SCIP_Real absval;
9568  SCIP_Real varlb;
9569  SCIP_Real varub;
9570  SCIP_Bool iscont;
9571  int nlocks;
9572 
9573  assert(vars != NULL);
9574  assert(vals != NULL);
9575 
9576  var = vars[v];
9577  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDown(var) >= 1); /* because variable is locked in this equality */
9578  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUp(var) >= 1);
9579  varlb = SCIPvarGetLbGlobal(var);
9580  varub = SCIPvarGetUbGlobal(var);
9581 
9582  val = vals[v];
9583  absval = REALABS(val);
9584  assert(SCIPisPositive(scip, absval));
9585 
9586  /* calculate minimal and maximal absolute value */
9587  if( absval < minabsval )
9588  minabsval = absval;
9589  if( absval > maxabsval )
9590  maxabsval = absval;
9591 
9592  /* do not try to multi aggregate, when numerical bad */
9593  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
9594  return SCIP_OKAY;
9595 
9596  slacktype = SCIPvarGetType(var);
9597  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9598  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9599  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9600  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9601 
9602  /* update candidates for continuous -> implint and integer -> implint conversion */
9603  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9604  {
9605  ncontvars++;
9606  contvarpos = v;
9607  }
9608  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9609  {
9610  ++nimplvars;
9611  }
9612  else if( slacktype == SCIP_VARTYPE_INTEGER )
9613  {
9614  nintvars++;
9615  intvarpos = v;
9616  }
9617 
9618  /* check, if variable is already fixed or aggregated */
9619  if( !SCIPvarIsActive(var) )
9620  continue;
9621 
9622  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9623  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
9624 
9625  if( nlocks > maxnlocksremove )
9626  continue;
9627 
9628  /* check, if variable can be used as a slack variable */
9629  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9630  !SCIPdoNotMultaggrVar(scip, var) )
9631  {
9632  SCIP_Bool better;
9633  SCIP_Bool equal;
9634  SCIP_Real slackdomrng;
9635 
9636  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9637  slackdomrng = SCIPinfinity(scip);
9638  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9639  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9640  return SCIP_OKAY;
9641  else
9642  {
9643  slackdomrng = (varub - varlb)*absval;
9644  assert(!SCIPisInfinity(scip, slackdomrng));
9645  }
9646  equal = FALSE;
9647  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9648  if( !better && slacktype == bestslacktype )
9649  {
9650  better = (nlocks < bestnlocks);
9651  if( nlocks == bestnlocks && !bestremovescons )
9652  {
9653  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9654  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9655  }
9656  }
9657 
9658  if( better || equal )
9659  {
9660  SCIP_Real minresactivity;
9661  SCIP_Real maxresactivity;
9662  SCIP_Real newlhs;
9663  SCIP_Real newrhs;
9664  SCIP_Bool removescons;
9665  SCIP_Bool minisrelax;
9666  SCIP_Bool maxisrelax;
9667  SCIP_Bool isminsettoinfinity;
9668  SCIP_Bool ismaxsettoinfinity;
9669 
9670  /* check if the constraint becomes redundant after multi-aggregation */
9671  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9672  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9673 
9674  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9675  * activity
9676  */
9677  if( minisrelax || maxisrelax )
9678  continue;
9679 
9680  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9681  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9682 
9683  /* check resactivities for reliability */
9684  if( removescons )
9685  {
9686  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9687  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9688 
9689  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9690  && SCIPisFeasLE(scip, newlhs, minresactivity))
9691  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9692 
9693  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9694  }
9695 
9696  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9697  if( conshdlrdata->multaggrremove && !removescons )
9698  continue;
9699 
9700  /* prefer variables that make the constraints redundant */
9701  if( bestremovescons && !removescons )
9702  continue;
9703 
9704  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9705  * other constraints
9706  */
9707  if( !removescons && nlocks > maxnlocksstay )
9708  continue;
9709 
9710  better = better || (!bestremovescons && removescons);
9711  if( better )
9712  {
9713  bestslackpos = v;
9714  bestslacktype = slacktype;
9715  bestnlocks = nlocks;
9716  bestslackdomrng = slackdomrng;
9717  bestremovescons = removescons;
9718  }
9719  }
9720  }
9721  }
9722 
9723  /* if all coefficients and variables are integral, the right hand side must also be integral */
9724  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9725  {
9726  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9727  SCIPdebugPrintCons(scip, cons, NULL);
9728  *cutoff = TRUE;
9729  return SCIP_OKAY;
9730  }
9731 
9732  supinf = 0;
9733  infinf = 0;
9734  samevar = FALSE;
9735 
9736  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9737  for( v = 0; v < consdata->nvars; ++v )
9738  {
9739  if( v != bestslackpos )
9740  {
9741  if( SCIPisPositive(scip, consdata->vals[v]) )
9742  {
9743  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9744  {
9745  ++supinf;
9746  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9747  {
9748  ++infinf;
9749  samevar = TRUE;
9750  }
9751  }
9752  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9753  ++infinf;
9754 
9755  }
9756  else if( SCIPisNegative(scip, consdata->vals[v]) )
9757  {
9758  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9759  {
9760  ++supinf;
9761  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9762  {
9763  ++infinf;
9764  samevar = TRUE;
9765  }
9766  }
9767  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9768  ++infinf;
9769  }
9770  }
9771  }
9772  assert(!samevar || (supinf > 0 && infinf > 0));
9773 
9774  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9775  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9776  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9777  {
9778  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9779  return SCIP_OKAY;
9780  }
9781 
9782  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9783  * we cannot aggregate the variable, because the integrality condition would get lost
9784  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9785  * loose the integrality condition for this variable.
9786  */
9787  if( bestslackpos >= 0
9788  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9789  || (coefsintegral && varsintegral && nimplvars == 0)) )
9790  {
9791  SCIP_VAR* slackvar;
9792  SCIP_Real* scalars;
9793  SCIP_Real slackcoef;
9794  SCIP_Real aggrconst;
9795  SCIP_Real newlhs;
9796  SCIP_Real newrhs;
9797  SCIP_Bool aggregated;
9798 
9799  /* we found a slack variable that only occurs in at most one other constraint:
9800  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9801  */
9802  assert(bestslackpos < consdata->nvars);
9803 
9804  /* do not multi aggregate binary variables */
9805  if( SCIPvarIsBinary(vars[bestslackpos]) )
9806  return SCIP_OKAY;
9807 
9808  /* convert equality into inequality by deleting the slack variable:
9809  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9810  */
9811  slackvar = vars[bestslackpos];
9812  slackcoef = vals[bestslackpos];
9813  assert(!SCIPisZero(scip, slackcoef));
9814  aggrconst = consdata->rhs/slackcoef;
9815 
9816  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9817  assert(SCIPisLE(scip, newlhs, newrhs));
9818  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9819  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9820  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9821 
9822  /* allocate temporary memory */
9823  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9824 
9825  /* set up the multi-aggregation */
9826  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9827  for( v = 0; v < consdata->nvars; ++v )
9828  {
9829  scalars[v] = -consdata->vals[v]/slackcoef;
9830  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9831  }
9832  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9833  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9834  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9835 
9836  /* perform the multi-aggregation */
9837  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9838  &infeasible, &aggregated) );
9839  assert(aggregated);
9840 
9841  /* free temporary memory */
9842  SCIPfreeBufferArray(scip, &scalars);
9843 
9844  /* check for infeasible aggregation */
9845  if( infeasible )
9846  {
9847  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9848  *cutoff = TRUE;
9849  return SCIP_OKAY;
9850  }
9851 
9852  (*naggrvars)++;
9853 
9854  /* delete the constraint if it became redundant */
9855  if( bestremovescons )
9856  {
9857  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9858  SCIP_CALL( SCIPdelCons(scip, cons) );
9859 
9860  if( !consdata->upgraded )
9861  (*ndelconss)++;
9862  }
9863  }
9864  else if( ncontvars == 1 )
9865  {
9866  SCIP_VAR* var;
9867 
9868  assert(0 <= contvarpos && contvarpos < consdata->nvars);
9869  var = vars[contvarpos];
9870  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
9871 
9872  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9873  {
9874  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
9875  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9876  {
9877  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9878  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
9879  SCIPconsGetName(cons), SCIPvarGetName(var));
9880  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9881  if( infeasible )
9882  {
9883  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9884  *cutoff = TRUE;
9885 
9886  return SCIP_OKAY;
9887  }
9888  }
9889  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
9890  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9891  else if( !SCIPdoNotAggr(scip) )
9892  {
9893  SCIP_VAR* newvar;
9894  SCIP_Real absval;
9895  char newvarname[SCIP_MAXSTRLEN];
9896  SCIP_Bool redundant;
9897  SCIP_Bool aggregated;
9898 
9899  absval = REALABS(vals[contvarpos]);
9900 
9901  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
9902 
9903  /* create new implicit variable for aggregation */
9904  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
9905  SCIP_VARTYPE_IMPLINT, SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) );
9906 
9907  /* add new variable to problem */
9908  SCIP_CALL( SCIPaddVar(scip, newvar) );
9909 
9910 #ifdef WITH_DEBUG_SOLUTION
9911  if( SCIPdebugIsMainscip(scip) )
9912  {
9913  SCIP_Real varval;
9914  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
9915  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
9916  }
9917 #endif
9918 
9919  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9920  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
9921  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
9922 
9923  /* aggregate continuous and implicit variable */
9924  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
9925 
9926  if( infeasible )
9927  {
9928  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
9929  SCIPvarGetName(var), SCIPvarGetName(newvar));
9930  *cutoff = TRUE;
9931 
9932  /* release implicit variable */
9933  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9934 
9935  return SCIP_OKAY;
9936  }
9937 
9938  /* release implicit variable */
9939  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9940 
9941  if( aggregated )
9942  (*naggrvars)++;
9943  else
9944  return SCIP_OKAY;
9945  }
9946 
9947  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
9948  * again
9949  */
9950  consdata->boundstightened = 0;
9951  consdata->rangedrowpropagated = 0;
9952  consdata->presolved = FALSE;
9953  }
9954  }
9955  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
9956  {
9957  SCIP_VAR* var;
9958 
9959  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
9960  * -> we don't convert integers into implints if the row is a 0/1-row
9961  */
9962  assert(varsintegral);
9963  assert(0 <= intvarpos && intvarpos < consdata->nvars);
9964  var = vars[intvarpos];
9965  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
9966 
9967  if( coefsintegral
9968  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
9969  && SCIPisFeasIntegral(scip, consdata->rhs) )
9970  {
9971  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
9972  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
9973  SCIPconsGetName(cons), SCIPvarGetName(var));
9974  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9975  if( infeasible )
9976  {
9977  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9978  *cutoff = TRUE;
9979 
9980  return SCIP_OKAY;
9981  }
9982  }
9983  }
9984 
9985  return SCIP_OKAY;
9986 }
9987 
9988 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
9989 static
9991  SCIP* scip, /**< SCIP data structure */
9992  SCIP_CONSDATA* consdata, /**< linear constraint data */
9993  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
9994  * objective function */
9995  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
9996  * this constraint */
9997  )
9998 {
9999  SCIP_VAR** vars;
10000  SCIP_VAR* var;
10001  SCIP_Real objval;
10002  SCIP_Bool negated;
10003  int nvars;
10004  int v;
10005 
10006  vars = consdata->vars;
10007  nvars = consdata->nvars;
10008 
10009  assert(vars != NULL);
10010 
10011  for( v = 0; v < nvars; ++v )
10012  {
10013  negated = FALSE;
10014  var = vars[v];
10015  assert(var != NULL);
10016 
10017  if( SCIPvarIsNegated(var) )
10018  {
10019  negated = TRUE;
10020  var = SCIPvarGetNegatedVar(var);
10021  assert(var != NULL);
10022  }
10023 
10024  objval = SCIPvarGetObj(var);
10025 
10026  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10027  * function
10028  */
10029  if( SCIPisZero(scip, objval) )
10030  return FALSE;
10031  else
10032  {
10033  SCIP_Real val;
10034 
10035  val = consdata->vals[v];
10036 
10037  if( negated )
10038  {
10039  if( v == 0 )
10040  {
10041  /* the first variable defines the scale */
10042  (*scale) = val / -objval;
10043 
10044  (*offset) += val;
10045  }
10046  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10047  (*offset) += val;
10048  else
10049  return FALSE;
10050  }
10051  else if( v == 0 )
10052  {
10053  /* the first variable defines the scale */
10054  (*scale) = val / objval;
10055  }
10056  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10057  return FALSE;
10058  }
10059  }
10060 
10061  return TRUE;
10062 }
10063 
10064 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10065  * objective coefficients and add an objective offset
10066  */
10067 static
10069  SCIP* scip, /**< SCIP data structure */
10070  SCIP_CONS* cons, /**< linear equation constraint */
10071  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10072  )
10073 {
10074  SCIP_CONSDATA* consdata;
10075  SCIP_Real offset;
10076  SCIP_Real scale;
10077  SCIP_Bool applicable;
10078  int nobjvars;
10079  int nvars;
10080  int v;
10081 
10082  assert(scip != NULL);
10083  assert(cons != NULL);
10084  assert(conshdlrdata != NULL);
10086  consdata = SCIPconsGetData(cons);
10087  assert(consdata != NULL);
10088  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10089 
10090  nvars = consdata->nvars;
10091  nobjvars = SCIPgetNObjVars(scip);
10092 
10093  /* check if the linear equality constraints does not have more variables than the objective function */
10094  if( nvars > nobjvars || nvars == 0 )
10095  return SCIP_OKAY;
10096 
10097  /* check for allowance of algorithm */
10098  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10099  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10100  return SCIP_OKAY;
10101 
10102  offset = consdata->rhs;
10103  scale = 1.0;
10104 
10105  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10106  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10107 
10108  if( applicable )
10109  {
10110  SCIP_VAR** vars;
10111 
10112  vars = consdata->vars;
10113  assert(vars != NULL);
10114 
10115  offset /= scale;
10116 
10117  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10118  SCIPconsGetName(cons), consdata->rhs, offset);
10119 
10120  /* set all objective coefficient to zero */
10121  for( v = 0; v < nvars; ++v )
10122  {
10123  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10124  }
10125 
10126  /* add an objective offset */
10127  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10128  }
10129 
10130  return SCIP_OKAY;
10131 }
10132 
10133 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10134 static
10136  SCIP* scip, /**< SCIP data structure */
10137  SCIP_CONS* cons, /**< constraint */
10138  SCIP_Real primalbound /**< feasible primal bound */
10139  )
10140 {
10141  SCIP_Real cutoffbound;
10142 
10143  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10144  * accepted
10145  */
10146  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10147 
10148  if( cutoffbound < SCIPgetCutoffbound(scip) )
10149  {
10150  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10151 
10152  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10153  }
10154  else
10155  {
10156  SCIP_CONSDATA* consdata;
10157 
10158  consdata = SCIPconsGetData(cons);
10159  assert(consdata != NULL);
10160 
10161  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10162  * resulted from one side
10163  */
10164  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10165  {
10166  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10167  * propagation
10168  */
10169  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10170  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10171  }
10172  }
10173 
10174  return SCIP_OKAY;
10175 }
10176 
10177 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10178  * constraint enters the LP by setting the initial and separated flag to FALSE
10179  */
10180 static
10182  SCIP* scip, /**< SCIP data structure */
10183  SCIP_CONS* cons, /**< linear constraint */
10184  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10185  )
10186 {
10187  SCIP_CONSDATA* consdata;
10188  SCIP_Real offset;
10189  SCIP_Real scale;
10190  SCIP_Bool applicable;
10191  int nobjvars;
10192  int nvars;
10193 
10194  assert(scip != NULL);
10195  assert(cons != NULL);
10196  assert(conshdlrdata != NULL);
10197 
10198  consdata = SCIPconsGetData(cons);
10199  assert(consdata != NULL);
10200 
10201  /* ignore equalities since these are covered by the method checkPartialObjective() */
10202  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10203  return SCIP_OKAY;
10204 
10205  nvars = consdata->nvars;
10206  nobjvars = SCIPgetNObjVars(scip);
10207 
10208  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10209  * initial and/or separated flag is set to FALSE
10210  */
10211  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10212  return SCIP_OKAY;
10213 
10214  offset = 0.0;
10215  scale = 1.0;
10216 
10217  /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10218  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10219  */
10220  if( nobjvars == 0 )
10221  return SCIP_OKAY;
10222 
10223  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10224  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10225 
10226  if( applicable )
10227  {
10228  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10229  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10230 
10231  if( SCIPisPositive(scip, scale) )
10232  {
10233  if( conshdlrdata->detectcutoffbound && rhsfinite )
10234  {
10235  SCIP_Real primalbound;
10236 
10237  primalbound = (consdata->rhs - offset) / scale;
10238 
10239  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10240  SCIPconsGetName(cons), primalbound);
10241 
10242  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10243  }
10244 
10245  if( conshdlrdata->detectlowerbound && lhsfinite )
10246  {
10247  SCIP_Real lowerbound;
10248 
10249  lowerbound = (consdata->lhs - offset) / scale;
10250 
10251  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10252  SCIPconsGetName(cons), lowerbound);
10253 
10254  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10255  }
10256 
10257  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10258  (conshdlrdata->detectlowerbound && !rhsfinite) )
10259  {
10260  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10261  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10262  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10263  }
10264  }
10265  else
10266  {
10267  if( conshdlrdata->detectlowerbound && rhsfinite )
10268  {
10269  SCIP_Real lowerbound;
10270 
10271  lowerbound = (consdata->rhs - offset) / scale;
10272 
10273  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10274  SCIPconsGetName(cons), lowerbound);
10275 
10276  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10277  }
10278 
10279  if( conshdlrdata->detectcutoffbound && lhsfinite )
10280  {
10281  SCIP_Real primalbound;
10282 
10283  primalbound = (consdata->lhs - offset) / scale;
10284 
10285  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10286  SCIPconsGetName(cons), primalbound);
10287 
10288  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10289  }
10290 
10291  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10292  (conshdlrdata->detectlowerbound && !lhsfinite) )
10293  {
10294  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10295  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10296  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10297  }
10298  }
10299  }
10300 
10301  return SCIP_OKAY;
10302 }
10303 
10304 /** converts special equalities */
10305 static
10307  SCIP* scip, /**< SCIP data structure */
10308  SCIP_CONS* cons, /**< linear constraint */
10309  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10310  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10311  int* nfixedvars, /**< pointer to count number of fixed variables */
10312  int* naggrvars, /**< pointer to count number of aggregated variables */
10313  int* ndelconss /**< pointer to count number of deleted constraints */
10314  )
10315 {
10316  SCIP_CONSDATA* consdata;
10317 
10318  assert(scip != NULL);
10319  assert(cons != NULL);
10320  assert(conshdlrdata != NULL);
10321  assert(cutoff != NULL);
10322  assert(nfixedvars != NULL);
10323  assert(naggrvars != NULL);
10324  assert(ndelconss != NULL);
10325 
10326  consdata = SCIPconsGetData(cons);
10327  assert(consdata != NULL);
10328  assert(consdata->removedfixings);
10329 
10330  /* do nothing on inequalities */
10331  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10332  return SCIP_OKAY;
10333 
10334  /* depending on the number of variables, call a special conversion method */
10335  if( consdata->nvars == 1 )
10336  {
10337  /* fix variable */
10338  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10339  }
10340  else if( consdata->nvars == 2 )
10341  {
10342  /* aggregate one of the variables */
10343  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10344  }
10345  else
10346  {
10347  /* check if the equality is part of the objective function */
10348  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10349 
10350  /* try to multi-aggregate one of the variables */
10351  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10352  }
10353 
10354  return SCIP_OKAY;
10355 }
10356 
10357 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10358  * integral
10359  */
10360 static
10362  SCIP* scip, /**< SCIP data structure */
10363  SCIP_CONSDATA* consdata, /**< linear constraint */
10364  int pos, /**< position of variable to be left out */
10365  SCIP_Real val /**< value to divide the coefficients by */
10366  )
10367 {
10368  int v;
10369 
10370  assert(scip != NULL);
10371  assert(consdata != NULL);
10372  assert(0 <= pos && pos < consdata->nvars);
10373 
10374  for( v = 0; v < consdata->nvars; ++v )
10375  {
10376  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10377  return FALSE;
10378  }
10379 
10380  return TRUE;
10381 }
10382 
10383 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10384  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10385  */
10386 static
10388  SCIP* scip, /**< SCIP data structure */
10389  SCIP_Real side, /**< lhs or rhs */
10390  SCIP_Real val, /**< coefficient */
10391  SCIP_Real minresactivity, /**< minimal residual activity */
10392  SCIP_Real maxresactivity, /**< maximal residual activity */
10393  SCIP_Real* minval, /**< pointer to store calculated minval */
10394  SCIP_Real* maxval /**< pointer to store calculated maxval */
10395  )
10396 {
10397  assert(scip != NULL);
10398  assert(minval != NULL);
10399  assert(maxval != NULL);
10400 
10401  if( val > 0.0 )
10402  {
10403  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10404  *minval = -maxresactivity;
10405  else
10406  *minval = (side - maxresactivity)/val;
10407 
10408  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10409  *maxval = -minresactivity;
10410  else
10411  *maxval = (side - minresactivity)/val;
10412  }
10413  else
10414  {
10415  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10416  *minval = minresactivity;
10417  else
10418  *minval = (side - minresactivity)/val;
10419 
10420  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10421  *maxval = maxresactivity;
10422  else
10423  *maxval = (side - maxresactivity)/val;
10424  }
10425 }
10426 
10427 
10428 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10429  * linear inequality
10430  */
10431 static
10433  SCIP* scip, /**< SCIP data structure */
10434  SCIP_CONS* cons, /**< linear constraint */
10435  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10436  int* nfixedvars, /**< pointer to count number of fixed variables */
10437  int* naggrvars, /**< pointer to count number of aggregated variables */
10438  int* ndelconss /**< pointer to count number of deleted constraints */
10439  )
10440 {
10441  SCIP_CONSDATA* consdata;
10442  SCIP_Bool lhsexists;
10443  SCIP_Bool rhsexists;
10444  SCIP_Bool bestisint;
10445  SCIP_Bool bestislhs;
10446  int bestpos;
10447  int i;
10448  int maxotherlocks;
10450  assert(scip != NULL);
10451  assert(cons != NULL);
10452  assert(cutoff != NULL);
10453  assert(nfixedvars != NULL);
10454  assert(naggrvars != NULL);
10455  assert(ndelconss != NULL);
10456 
10457  /* only process checked constraints (for which the locks are increased);
10458  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10459  * dualfix presolver
10460  */
10461  if( !SCIPconsIsChecked(cons) )
10462  return SCIP_OKAY;
10463 
10464  consdata = SCIPconsGetData(cons);
10465  assert(consdata != NULL);
10466 
10467  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10468  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10469 
10470  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10471  * can use it safely for aggregation and break the search loop
10472  */
10473  bestpos = -1;
10474  bestisint = TRUE;
10475  bestislhs = FALSE;
10476 
10477  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10478  * everything else would produce fill-in. Exceptions:
10479  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10480  * produced.
10481  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10482  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10483  * six nonzeros (two variables per substitution).
10484  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10485  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10486  * six nonzeros (three variables per substitution). God exists!
10487  */
10488  if( consdata->nvars <= 2 )
10489  maxotherlocks = INT_MAX;
10490  else if( consdata->nvars == 3 )
10491  maxotherlocks = 3;
10492  else if( consdata->nvars == 4 )
10493  maxotherlocks = 2;
10494  else
10495  maxotherlocks = 1;
10496 
10497  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10498  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10499  maxotherlocks++;
10500 
10501  for( i = 0; i < consdata->nvars && bestisint; ++i )
10502  {
10503  SCIP_VAR* var;
10504  SCIP_Bool isint;
10505  SCIP_Real val;
10506  SCIP_Real obj;
10507  SCIP_Real lb;
10508  SCIP_Real ub;
10509  SCIP_Bool agglhs;
10510  SCIP_Bool aggrhs;
10511 
10512  var = consdata->vars[i];
10514 
10515  /* if we already found a candidate, skip integers */
10516  if( bestpos >= 0 && isint )
10517  continue;
10518 
10519  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10520  * active, fixed, or single-aggregated with another binary variable
10521  */
10522  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10523  continue;
10524 
10525  if ( SCIPdoNotMultaggrVar(scip, var) )
10526  continue;
10527 
10528  val = consdata->vals[i];
10529  obj = SCIPvarGetObj(var);
10530  lb = SCIPvarGetLbGlobal(var);
10531  ub = SCIPvarGetUbGlobal(var);
10532 
10533  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10534  *
10535  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10536  * - constraint is the only one that forbids fixing the variable to its lower bound
10537  * - 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
10538  *
10539  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10540  * - constraint is the only one that forbids fixing the variable to its upper bound
10541  * - 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
10542  *
10543  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10544  * - constraint is the only one that forbids fixing the variable to its upper bound
10545  * - 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
10546  *
10547  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10548  * - constraint is the only one that forbids fixing the variable to its lower bound
10549  * - 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
10550  *
10551  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10552  * of all x_j
10553  * furthermore: we only want to apply this, if no fill-in will be produced
10554  */
10555  agglhs = lhsexists
10556  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10557  && SCIPvarGetNLocksUp(var) <= maxotherlocks)
10558  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10559  && SCIPvarGetNLocksDown(var) <= maxotherlocks));
10560  aggrhs = rhsexists
10561  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10562  && SCIPvarGetNLocksDown(var) <= maxotherlocks)
10563  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10564  && SCIPvarGetNLocksUp(var) <= maxotherlocks));
10565  if( agglhs || aggrhs )
10566  {
10567  SCIP_Real minresactivity;
10568  SCIP_Real maxresactivity;
10569  SCIP_Real minval;
10570  SCIP_Real maxval;
10571  SCIP_Bool minisrelax;
10572  SCIP_Bool maxisrelax;
10573  SCIP_Bool isminsettoinfinity;
10574  SCIP_Bool ismaxsettoinfinity;
10575 
10576  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10577  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10578  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10579  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10580 
10581  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10582  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10583  * This is needed, because we do not want to rely on relaxed finite resactivities.
10584  */
10585  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10586 
10587  if( agglhs )
10588  {
10589  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10590  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10591 
10592  assert(SCIPisLE(scip, minval, maxval));
10593  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10594  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10595  {
10596  SCIP_Real oldmaxresactivity;
10597  SCIP_Real oldminresactivity;
10598  SCIP_Bool recalculated;
10599 
10600  recalculated = FALSE;
10601  oldmaxresactivity = maxresactivity;
10602  oldminresactivity = minresactivity;
10603 
10604  /* check minresactivity for reliability */
10605  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10606  {
10607  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10608  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10609  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10610  }
10611 
10612  /* check maxresactivity for reliability */
10613  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10614  {
10615  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10616  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10617  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10618  }
10619 
10620  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10621  if( recalculated )
10622  {
10623  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10624 
10625  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10626  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10627 
10628  assert(SCIPisLE(scip, minval, maxval));
10629  }
10630 
10631  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10632  {
10633  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10634  * in the multi-aggregation
10635  */
10636  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10637  {
10638  bestpos = i;
10639  bestisint = isint;
10640  bestislhs = TRUE;
10641  continue; /* no need to also look at the right hand side */
10642  }
10643  }
10644  }
10645  }
10646 
10647  if( aggrhs )
10648  {
10649  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10650  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10651 
10652  assert(SCIPisLE(scip,minval,maxval));
10653  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10654  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10655  {
10656  SCIP_Real oldmaxresactivity;
10657  SCIP_Real oldminresactivity;
10658  SCIP_Bool recalculated;
10659 
10660  recalculated = FALSE;
10661  oldmaxresactivity = maxresactivity;
10662  oldminresactivity = minresactivity;
10663 
10664  /* check minresactivity for reliability */
10665  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10666  {
10667  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10668  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10669  }
10670 
10671  /* check maxresactivity for reliability */
10672  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10673  {
10674  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10675  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10676  }
10677 
10678  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10679  if( recalculated )
10680  {
10681  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10682  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10683  assert(SCIPisLE(scip,minval,maxval));
10684  }
10685 
10686  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10687  {
10688  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10689  * in the multi-aggregation
10690  */
10691  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10692  {
10693  bestpos = i;
10694  bestisint = isint;
10695  bestislhs = FALSE;
10696  }
10697  }
10698  }
10699  }
10700  }
10701  }
10702 
10703  if( bestpos >= 0 )
10704  {
10705  SCIP_VAR** aggrvars;
10706  SCIP_Real* aggrcoefs;
10707  SCIP_Real aggrconst;
10708  SCIP_VAR* bestvar;
10709  SCIP_Real bestval;
10710  SCIP_Real epsilon;
10711  int naggrs;
10712  int j;
10713  SCIP_Bool infeasible;
10714  SCIP_Bool aggregated;
10715  SCIP_Bool samevar;
10716  int supinf; /* counter for infinite contributions to the supremum of a possible
10717  * multi-aggregation
10718  */
10719  int infinf; /* counter for infinite contributions to the infimum of a possible
10720  * multi-aggregation
10721  */
10722 
10723  assert(!bestislhs || lhsexists);
10724  assert(bestislhs || rhsexists);
10725 
10726  bestvar = consdata->vars[bestpos];
10727  bestval = consdata->vals[bestpos];
10728  assert(bestisint ==
10730 
10731  /* allocate temporary memory */
10732  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10733  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10734 
10735  /* set up the multi-aggregation */
10736  SCIPdebugPrintCons(scip, cons, NULL);
10737  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10738  naggrs = 0;
10739  supinf = 0;
10740  infinf = 0;
10741  samevar = FALSE;
10742  epsilon = SCIPepsilon(scip);
10743 
10744  for( j = 0; j < consdata->nvars; ++j )
10745  {
10746  if( j != bestpos )
10747  {
10748  SCIP_Real absaggrcoef;
10749 
10750  aggrvars[naggrs] = consdata->vars[j];
10751  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10752  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10753 
10754  absaggrcoef = REALABS(aggrcoefs[naggrs]);
10755 
10756  /* do not try to multi aggregate, when numerical bad */
10757  if( absaggrcoef < epsilon )
10758  {
10759  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10760 
10761  /* free temporary memory */
10762  SCIPfreeBufferArray(scip, &aggrcoefs);
10763  SCIPfreeBufferArray(scip, &aggrvars);
10764 
10765  return SCIP_OKAY;
10766  }
10767 
10768  if( bestisint )
10769  {
10770  /* coefficient must be integral: round it to exact integral value */
10771  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10772  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10773  }
10774 
10775  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10776  {
10777  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10778  {
10779  ++supinf;
10780  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10781  {
10782  ++infinf;
10783  samevar = TRUE;
10784  }
10785  }
10786  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10787  ++infinf;
10788  }
10789  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10790  {
10791  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10792  {
10793  ++supinf;
10794  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10795  {
10796  ++infinf;
10797  samevar = TRUE;
10798  }
10799  }
10800  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10801  ++infinf;
10802  }
10803 
10804  naggrs++;
10805  }
10806  }
10807  assert(!samevar || (supinf > 0 && infinf > 0));
10808 
10809  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10810  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10811  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10812  assert(naggrs == consdata->nvars-1);
10813 
10814  /* right hand side must be integral: round it to exact integral value */
10815  if( bestisint )
10816  {
10817  assert(SCIPisIntegral(scip, aggrconst));
10818  aggrconst = SCIPfloor(scip, aggrconst+0.5);
10819  }
10820 
10821  aggregated = FALSE;
10822  infeasible = FALSE;
10823 
10824  /* perform the multi-aggregation */
10825  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
10826  {
10827  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
10828  * also convertLongEquality() early termination due to coefficients
10829  */
10830  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10831  }
10832  else
10833  {
10834  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10835  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10836  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10837  }
10838  /* free temporary memory */
10839  SCIPfreeBufferArray(scip, &aggrcoefs);
10840  SCIPfreeBufferArray(scip, &aggrvars);
10841 
10842  /* check for infeasible aggregation */
10843  if( infeasible )
10844  {
10845  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10846  *cutoff = TRUE;
10847  return SCIP_OKAY;
10848  }
10849 
10850  /* delete the constraint, if the aggregation was successful */
10851  if( aggregated )
10852  {
10853  SCIP_CALL( SCIPdelCons(scip, cons) );
10854 
10855  if( !consdata->upgraded )
10856  (*ndelconss)++;
10857  (*naggrvars)++;
10858  }
10859  else
10860  {
10861  SCIPdebugMsg(scip, "aggregation non successful!\n");
10862  }
10863  }
10864 
10865  return SCIP_OKAY;
10866 }
10867 
10868 #define BINWEIGHT 1
10869 #define INTWEIGHT 4
10870 #define CONTWEIGHT 8
10871 
10872 /** gets weight for variable in a "weighted number of variables" sum */
10873 static
10874 int getVarWeight(
10875  SCIP_VAR* var /**< variable to get weight for */
10876  )
10877 {
10878  switch( SCIPvarGetType(var) )
10879  {
10880  case SCIP_VARTYPE_BINARY:
10881  return BINWEIGHT;
10882  case SCIP_VARTYPE_INTEGER:
10883  case SCIP_VARTYPE_IMPLINT:
10884  return INTWEIGHT;
10886  return CONTWEIGHT;
10887  default:
10888  SCIPerrorMessage("invalid variable type\n");
10889  SCIPABORT();
10890  return 0; /*lint !e527*/
10891  }
10892 }
10893 
10894 /** tries to aggregate variables in equations a^Tx = lhs
10895  * in case there are at most two binary variables with an odd coefficient and all other
10896  * variables are not continuous and have an even coefficient then:
10897  * - exactly one odd binary variables
10898  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
10899  * - lhs is odd -> y = 1
10900  * - lhs is even -> y = 0
10901  * - exactly two odd binary variables
10902  * aggregate the two binary variables with odd coefficient
10903  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
10904  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
10905  */
10906 static
10908  SCIP* scip, /**< SCIP data structure */
10909  SCIP_CONS* cons, /**< linear constraint */
10910  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10911  int* nfixedvars, /**< pointer to count number of fixed variables */
10912  int* naggrvars, /**< pointer to count number of aggregated variables */
10913  int* ndelconss /**< pointer to count number of deleted constraints */
10914  )
10915 { /*lint --e{715}*/
10916  SCIP_CONSDATA* consdata;
10917  SCIP_Bool success;
10918 
10919  assert( scip != NULL );
10920  assert( cons != NULL );
10921 
10922  consdata = SCIPconsGetData(cons);
10923  assert( consdata != NULL );
10925  /* check if the linear constraint is an equation with integral right hand side */
10926  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
10927  return SCIP_OKAY;
10928 
10929  /* try to fix and aggregated variables until nothing is possible anymore */
10930  do
10931  {
10932  int v;
10933  int nvars;
10934  SCIP_VAR** vars;
10935  SCIP_Real* vals;
10936  SCIP_Real lhs;
10937  SCIP_Bool lhsodd;
10938 
10939  SCIP_Bool infeasible;
10940  SCIP_Bool fixed;
10941  SCIP_Bool aggregated;
10942  SCIP_Bool redundant;
10943 
10944  SCIP_VAR* var1;
10945  SCIP_VAR* var2;
10946  int noddvars;
10947 
10948  success = FALSE;
10949 
10950  lhs = consdata->lhs;
10951  vars = consdata->vars;
10952  vals = consdata->vals;
10953  nvars = consdata->nvars;
10954 
10955  assert( !SCIPisInfinity(scip, ABS(lhs)) );
10956 
10957  var1 = NULL;
10958  var2 = NULL;
10959  noddvars = 0;
10960 
10961  /* search for binary variables with an odd coefficient */
10962  for( v = 0; v < nvars && noddvars < 3; ++v )
10963  {
10964  SCIP_Longint val;
10965 
10966  /* all coefficients and variables have to be integral */
10967  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10968  return SCIP_OKAY;
10969 
10970  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
10971  if( val % 2 != 0 )
10972  {
10973  /* the odd values have to belong to binary variables */
10974  if( !SCIPvarIsBinary(vars[v]) )
10975  return SCIP_OKAY;
10976 
10977  if( noddvars == 0 )
10978  var1 = vars[v];
10979  else
10980  var2 = vars[v];
10981 
10982  noddvars++;
10983  }
10984  }
10985 
10986  /* check lhs is odd or even */
10987  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
10988 
10989  if( noddvars == 1 )
10990  {
10991  assert( var1 != NULL );
10992 
10993  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
10994  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
10995 
10996  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
10997 
10998  /* check for infeasibility of fixing */
10999  if( infeasible )
11000  {
11001  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11002  *cutoff = TRUE;
11003  return SCIP_OKAY;
11004  }
11005 
11006  if( fixed )
11007  {
11008  SCIPdebugMsg(scip, " -> feasible fixing\n");
11009  (*nfixedvars)++;
11010  success = TRUE;
11011  }
11012  }
11013  else if( noddvars == 2 )
11014  {
11015  assert( var1 != NULL );
11016  assert( var2 != NULL );
11017 
11018  /* aggregate the two variables with odd coefficient
11019  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11020  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11021  */
11022  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11023  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11024 
11025  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11026  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11027 
11028  /* check for infeasibility of aggregation */
11029  if( infeasible )
11030  {
11031  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11032  *cutoff = TRUE;
11033  return SCIP_OKAY;
11034  }
11035 
11036  /* count the aggregation */
11037  if( aggregated )
11038  {
11039  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11040  (*naggrvars)++;
11041  success = TRUE;
11042  }
11043  }
11044 
11045  if( success )
11046  {
11047  /* apply fixings and aggregation to successfully rerun this presolving step */
11048  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11049 
11050  if( infeasible )
11051  {
11052  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11053  *cutoff = TRUE;
11054  return SCIP_OKAY;
11055  }
11056 
11057  /* normalize constraint */
11058  SCIP_CALL( normalizeCons(scip, cons) );
11059  }
11060  }
11061  while( success );
11062 
11063  return SCIP_OKAY;
11064 }
11065 
11066 
11067 
11068 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11069  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11070  * coefficients
11071  */
11072 static
11073 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11074 { /*lint --e{715}*/
11075  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11076  SCIP_VARTYPE vartype1;
11077  SCIP_VARTYPE vartype2;
11078  SCIP_Real value;
11079 
11080  assert(consdata != NULL);
11081  assert(0 <= ind1 && ind1 < consdata->nvars);
11082  assert(0 <= ind2 && ind2 < consdata->nvars);
11083 
11084  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11085  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11086 
11087  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11088  {
11089  /* continuous varibles will be sorted to the back */
11090  if( vartype2 != vartype1 )
11091  return +1;
11092  /* both variables are continuous */
11093  else
11094  return 0;
11095  }
11096  /* continuous variables will be sorted to the back */
11097  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11098  return -1;
11099 
11100  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11101 
11102  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11103  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11104 }
11105 
11106 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11107  * common divisor
11108  *
11109  * 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
11110  * constraint to 1^Tx = 1
11111  */
11112 static
11114  SCIP* scip, /**< SCIP data structure */
11115  SCIP_CONS* cons, /**< linear constraint */
11116  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11117  int* nchgsides /**< pointer to store the amount of changed sides */
11118  )
11119 {
11120  SCIP_CONSDATA* consdata;
11121  SCIP_VAR** vars;
11122  SCIP_Real* vals;
11123  SCIP_Real minval;
11124  SCIP_Real secondminval;
11125  SCIP_Real maxval;
11126  SCIP_Real lhs;
11127  SCIP_Real rhs;
11128  int nvars;
11129  int v;
11131  /* we must not change a modifiable constraint in any way */
11132  if( SCIPconsIsModifiable(cons) )
11133  return SCIP_OKAY;
11134 
11135  if( SCIPconsIsDeleted(cons) )
11136  return SCIP_OKAY;
11137 
11138  consdata = SCIPconsGetData(cons);
11139  assert(consdata != NULL);
11140 
11141  nvars = consdata->nvars;
11142 
11143  /* do not check empty or bound-constraints */
11144  if( nvars < 2 )
11145  return SCIP_OKAY;
11146 
11147  vals = consdata->vals;
11148  vars = consdata->vars;
11149  assert(vars != NULL);
11150  assert(vals != NULL);
11151 
11152  lhs = consdata->lhs;
11153  rhs = consdata->rhs;
11154  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11155  assert(!SCIPisNegative(scip, rhs));
11156 
11157  minval = SCIP_INVALID;
11158  secondminval = SCIP_INVALID;
11159  maxval = -SCIP_INVALID;
11160 
11161  for( v = nvars - 1; v >= 0; --v )
11162  {
11163  if( SCIPvarIsBinary(vars[v]) )
11164  {
11165  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11166  {
11167  secondminval = minval;
11168  minval = vals[v];
11169  }
11170  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11171  secondminval = vals[v];
11172 
11173  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11174  maxval = vals[v];
11175  }
11176  else
11177  break;
11178  }
11179 
11180  /* check if all variables are binary */
11181  if( v == -1 )
11182  {
11183  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11184  return SCIP_OKAY;
11185 
11186  /* check if we can and need to choose exactly one binary variable */
11187  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11188  {
11189  /* change all coefficients to 1.0 */
11190  for( v = nvars - 1; v >= 0; --v )
11191  {
11192  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11193  }
11194  (*nchgcoefs) += nvars;
11195 
11196  /* replace old right and left hand side with 1.0 */
11197  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11198  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11199  (*nchgsides) += 2;
11200  }
11201  }
11202 
11203  return SCIP_OKAY;
11204 }
11205 
11206 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11207  * for equations @see rangedRowSimplify() will be called
11208  *
11209  * there are several different coefficient reduction steps which will be applied
11210  *
11211  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11212  *
11213  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11214  *
11215  * 2. We try to remove redundant fractional parts in a constraint
11216  *
11217  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11218  *
11219  * 3. We are using the greatest common divisor for further reductions
11220  *
11221  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11222  * integral
11223  */
11224 static
11226  SCIP* scip, /**< SCIP data structure */
11227  SCIP_CONS* cons, /**< linear constraint */
11228  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11229  int* nchgsides /**< pointer to store the amount of changed sides */
11230  )
11231 {
11232  SCIP_CONSDATA* consdata;
11233  SCIP_VAR** vars;
11234  SCIP_Real* vals;
11235  int* perm;
11236  SCIP_Real minactsub;
11237  SCIP_Real maxactsub;
11238  SCIP_Real siderest;
11239  SCIP_Real feastol;
11240  SCIP_Real newcoef;
11241  SCIP_Real absval;
11243  SCIP_Real lhs;
11244  SCIP_Real rhs;
11245  SCIP_Real lb;
11246  SCIP_Real ub;
11247  SCIP_Longint restcoef;
11248  SCIP_Longint oldgcd;
11249  SCIP_Longint rest;
11250  SCIP_Longint gcd;
11251  SCIP_Bool isminsettoinfinity;
11252  SCIP_Bool ismaxsettoinfinity;
11253  SCIP_Bool isminrelax;
11254  SCIP_Bool ismaxrelax;
11255  SCIP_Bool allcoefintegral;
11256  SCIP_Bool onlybin;
11257  SCIP_Bool hasrhs;
11258  SCIP_Bool haslhs;
11259  int oldnchgcoefs;
11260  int oldnchgsides;
11261  int foundbin;
11262  int candpos;
11263  int candpos2;
11264  int offsetv;
11265  int nvars;
11266  int v;
11267  int w;
11268 
11269  assert(scip != NULL);
11270  assert(cons != NULL);
11271  assert(nchgcoefs != NULL);
11272  assert(nchgsides != NULL);
11273 
11274  /* we must not change a modifiable constraint in any way */
11275  if( SCIPconsIsModifiable(cons) )
11276  return SCIP_OKAY;
11277 
11278  if( SCIPconsIsDeleted(cons) )
11279  return SCIP_OKAY;
11280 
11281  consdata = SCIPconsGetData(cons);
11282  assert(consdata != NULL);
11283 
11284  nvars = consdata->nvars;
11285 
11286  /* do not check empty or bound-constraints */
11287  if( nvars <= 2 )
11288  return SCIP_OKAY;
11289 
11290  /* update maximal activity delta if necessary */
11291  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11292  consdataRecomputeMaxActivityDelta(scip, consdata);
11293 
11294  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11295  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11296  checkMaxActivityDelta(scip, consdata);
11297 
11298  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11299  * accordingly
11300  */
11301  /* can only work with valid non-infinity activities per variable */
11302  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11303  return SCIP_OKAY;
11304 
11305  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11306  * but the eventsystem seems to be full
11307  */
11308  consdata->normalized = FALSE;
11309 
11310  /* normalize constraint */
11311  SCIP_CALL( normalizeCons(scip, cons) );
11312  assert(nvars == consdata->nvars);
11313 
11314  if( !consdata->normalized )
11315  return SCIP_OKAY;
11316 
11317  lhs = consdata->lhs;
11318  rhs = consdata->rhs;
11319  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11320  assert(!SCIPisNegative(scip, rhs));
11321 
11322  if( !SCIPisInfinity(scip, -lhs) )
11323  haslhs = TRUE;
11324  else
11325  haslhs = FALSE;
11326 
11327  if( !SCIPisInfinity(scip, rhs) )
11328  hasrhs = TRUE;
11329  else
11330  hasrhs = FALSE;
11331 
11332  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11333  SCIPdebug( oldnchgsides = *nchgsides; )
11334 
11335  /* @todo also work on ranged rows */
11336  if( haslhs && hasrhs )
11337  {
11338  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11339 
11340  return SCIP_OKAY;
11341  }
11342  assert(haslhs != hasrhs);
11343 
11344  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11345  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11346  assert(!haslhs || !SCIPisNegative(scip, lhs));
11347 
11348  /* get temporary memory to store the sorted permutation */
11349  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11350 
11351  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11352  * value of their coefficients
11353  */
11354  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11355 
11356  /* perform sorting after permutation array */
11357  permSortConsdata(consdata, perm, nvars);
11358  consdata->sorted = FALSE;
11359  consdata->binvarssorted = FALSE;
11360 
11361  vars = consdata->vars;
11362  vals = consdata->vals;
11363  assert(vars != NULL);
11364  assert(vals != NULL);
11365  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11366 
11367  /* free temporary memory */
11368  SCIPfreeBufferArray(scip, &perm);
11369 
11370  /* only check constraints with at least two non continuous variables */
11371  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11372  return SCIP_OKAY;
11373 
11374  /* do not process constraints when all coefficients are 1.0 */
11375  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11376  return SCIP_OKAY;
11377 
11378  feastol = SCIPfeastol(scip);
11379 
11380  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11381  SCIPdebugPrintCons(scip, cons, NULL);
11382 
11383  /* get global activities */
11384  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11385  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11386 
11387  /* cannot work with infinite activities */
11388  if( isminsettoinfinity || ismaxsettoinfinity )
11389  return SCIP_OKAY;
11390 
11391  assert(!isminrelax);
11392  assert(!ismaxrelax);
11393  assert(maxactsub > minactsub);
11394  assert(!SCIPisInfinity(scip, -minactsub));
11395  assert(!SCIPisInfinity(scip, maxactsub));
11396 
11397  v = 0;
11398  offsetv = -1;
11399  side = haslhs ? lhs : rhs;
11400 
11401  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11402  * do not need to look at the large coefficients
11403  *
11404  * e.g. all x are binary, z are positive integer
11405  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11406  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11407  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11408  *
11409  * can be changed to
11410  *
11411  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11412  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11413  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11414  */
11415 
11416  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11417  * hand side, we cannot apply the extra reduction step and need to reset v
11418  *
11419  * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 for all i is not a solution, but if we would do a change on the
11420  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11421  * for all i is a solution
11422  *
11423  * also redundancy of variables would not be correctly determined in such a case
11424  */
11425  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11426  {
11427  v = 1;
11428 
11429  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11430  {
11431  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11432  * extra step, which might have worked
11433  */
11434  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11435  {
11436  v = 0;
11437  break;
11438  }
11439 
11440  ++v;
11441  }
11442 
11443  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11444  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11445  if( v == nvars )
11446  return SCIP_OKAY;
11447 
11448  /* cannot work with continuous variables which have a big coefficient */
11449  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11450  return SCIP_OKAY;
11451 
11452  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11453  if( SCIPisEQ(scip, side, -vals[v]) )
11454  v = 0;
11455 
11456  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11457  * reduction
11458  */
11459  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11460  v = 0;
11461 
11462  if( v > 0 )
11463  {
11464  assert(v < nvars);
11465 
11466  offsetv = v - 1;
11467 
11468  for( w = 0; w < v; ++w )
11469  {
11470  lb = SCIPvarGetLbGlobal(vars[w]);
11471  ub = SCIPvarGetUbGlobal(vars[w]);
11472 
11473  assert(vals[w] > 0);
11474 
11475  /* update residual activities */
11476  maxactsub -= ub * vals[w];
11477  minactsub -= lb * vals[w];
11478  assert(maxactsub > minactsub);
11479  }
11480  }
11481  }
11482 
11483  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11484  *
11485  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11486  *
11487  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11488  * to
11489  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11490  */
11491  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11492  {
11493  SCIP_Bool redundant = FALSE;
11494 
11495  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11496  assert(gcd >= 1);
11497 
11498  if( v == 0 )
11499  {
11500  lb = SCIPvarGetLbGlobal(vars[0]);
11501  ub = SCIPvarGetUbGlobal(vars[0]);
11502 
11503  /* update residual activities */
11504  if( vals[0] > 0 )
11505  {
11506  maxactsub -= ub * vals[0];
11507  minactsub -= lb * vals[0];
11508  }
11509  else
11510  {
11511  maxactsub -= lb * vals[0];
11512  minactsub -= ub * vals[0];
11513  }
11514  assert(maxactsub > minactsub);
11515  ++v;
11516  }
11517 
11518  siderest = -SCIP_INVALID;
11519  allcoefintegral = TRUE;
11520 
11521  /* check if some variables always fit into the given constraint */
11522  for( ; v < nvars - 1; ++v )
11523  {
11524  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11525  break;
11526 
11527  if( !SCIPisIntegral(scip, vals[v]) )
11528  {
11529  allcoefintegral = FALSE;
11530  break;
11531  }
11532 
11533  /* calculate greatest common divisor for all general and binary variables */
11534  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11535 
11536  if( gcd == 1 )
11537  break;
11538 
11539  lb = SCIPvarGetLbGlobal(vars[v]);
11540  ub = SCIPvarGetUbGlobal(vars[v]);
11541 
11542  assert(!SCIPisInfinity(scip, -lb));
11543  assert(!SCIPisInfinity(scip, ub));
11544 
11545  /* update residual activities */
11546  if( vals[v] > 0 )
11547  {
11548  maxactsub -= ub * vals[v];
11549  minactsub -= lb * vals[v];
11550  }
11551  else
11552  {
11553  maxactsub -= lb * vals[v];
11554  minactsub -= ub * vals[v];
11555  }
11556  assert(SCIPisGE(scip, maxactsub, minactsub));
11557 
11558  if( hasrhs )
11559  {
11560  /* determine the remainder of the right hand side and the gcd */
11561  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11562  }
11563  else
11564  {
11565  /* determine the remainder of the left hand side and the gcd */
11566  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11567  if( SCIPisZero(scip, siderest) )
11568  siderest = gcd;
11569  }
11570 
11571  /* early termination if the activities deceed the gcd */
11572  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11573  {
11574  redundant = TRUE;
11575  break;
11576  }
11577  }
11578  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11579 
11580  if( !redundant )
11581  {
11582  if( hasrhs )
11583  {
11584  /* determine the remainder of the right hand side and the gcd */
11585  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11586  }
11587  else
11588  {
11589  /* determine the remainder of the left hand side and the gcd */
11590  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11591  if( SCIPisZero(scip, siderest) )
11592  siderest = gcd;
11593  }
11594  }
11595  else
11596  ++v;
11597 
11598  SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n",
11599  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11600 
11601  /* check if we can remove redundant variables */
11602  if( v < nvars && (redundant ||
11603  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11604  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11605  {
11606  SCIP_Real oldcoef;
11607 
11608  /* double check the redundancy */
11609 #ifndef NDEBUG
11610  SCIP_Real tmpminactsub = 0.0;
11611  SCIP_Real tmpmaxactsub = 0.0;
11612 
11613  /* recompute residual activities */
11614  for( w = v; w < nvars; ++w )
11615  {
11616  lb = SCIPvarGetLbGlobal(vars[w]);
11617  ub = SCIPvarGetUbGlobal(vars[w]);
11618 
11619  assert(!SCIPisInfinity(scip, -lb));
11620  assert(!SCIPisInfinity(scip, ub));
11621 
11622  /* update residual activities */
11623  if( vals[w] > 0 )
11624  {
11625  tmpmaxactsub += ub * vals[w];
11626  tmpminactsub += lb * vals[w];
11627  }
11628  else
11629  {
11630  tmpmaxactsub += lb * vals[w];
11631  tmpminactsub += ub * vals[w];
11632  }
11633  assert(tmpmaxactsub >= tmpminactsub);
11634  }
11635 
11636  if( hasrhs )
11637  {
11638  assert(offsetv == -1);
11639 
11640  /* determine the remainder of the right hand side and the gcd */
11641  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11642  }
11643  else
11644  {
11645  /* determine the remainder of the left hand side and the gcd */
11646  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11647  if( SCIPisZero(scip, siderest) )
11648  siderest = gcd;
11649  }
11650 
11651  /* does the redundancy really is fulfilled */
11652  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11653 #endif
11654 
11655  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11656  nvars - v, SCIPconsGetName(cons));
11657 
11658  /* remove redundant variables */
11659  for( w = nvars - 1; w >= v; --w )
11660  {
11661  SCIP_CALL( delCoefPos(scip, cons, w) );
11662  }
11663  (*nchgcoefs) += (nvars - v);
11664 
11665  assert(w >= 0);
11666 
11667  oldcoef = vals[w];
11668 
11669  /* normalize constraint */
11670  SCIP_CALL( normalizeCons(scip, cons) );
11671  assert(vars == consdata->vars);
11672  assert(vals == consdata->vals);
11673  assert(w < consdata->nvars);
11674 
11675  /* compute new greatest common divisor due to normalization */
11676  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11677  assert(gcd >= 1);
11678 
11679  /* update side */
11680  if( hasrhs )
11681  {
11682  /* replace old with new right hand side */
11683  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11684  rhs = consdata->rhs;
11685  }
11686  else
11687  {
11688  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11689  {
11690  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11691  lhs = consdata->lhs;
11692  }
11693  else
11694  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11695  }
11696  ++(*nchgsides);
11697 
11698  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11699  assert(!haslhs || !SCIPisNegative(scip, lhs));
11700 
11701  /* get new constraint data */
11702  nvars = consdata->nvars;
11703  assert(nvars >= 2);
11704 
11705  allcoefintegral = TRUE;
11706 
11707 #ifndef NDEBUG
11708  /* check integrality */
11709  for( w = offsetv + 1; w < nvars; ++w )
11710  {
11711  assert(SCIPisIntegral(scip, vals[w]));
11712  }
11713 #endif
11714  SCIPdebugPrintCons(scip, cons, NULL);
11715  }
11716 
11717  /* try to find a better gcd, when having large coefficients */
11718  if( offsetv >= 0 && gcd == 1 )
11719  {
11720  /* calculate greatest common divisor for all general variables */
11721  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11722 
11723  if( gcd > 1 )
11724  {
11725  gcd = -1;
11726  candpos = -1;
11727 
11728  for( v = nvars - 1; v > offsetv; --v )
11729  {
11730  assert(!SCIPisZero(scip, vals[v]));
11731  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11732  break;
11733 
11734  if( !SCIPisIntegral(scip, vals[v]) )
11735  {
11736  allcoefintegral = FALSE;
11737  break;
11738  }
11739 
11740  oldgcd = gcd;
11741 
11742  if( gcd == -1 )
11743  {
11744  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11745  assert(gcd >= 1);
11746  }
11747  else
11748  {
11749  /* calculate greatest common divisor for all general and binary variables */
11750  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11751  }
11752 
11753  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11754  * can stop searching
11755  */
11756  if( gcd == 1 )
11757  {
11758  if( !SCIPvarIsBinary(vars[v]) )
11759  break;
11760 
11761  /* found candidate */
11762  if( candpos == -1 )
11763  {
11764  gcd = oldgcd;
11765  candpos = v;
11766  }
11767  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11768  else
11769  break;
11770  }
11771  }
11772  assert(v > offsetv || candpos > offsetv);
11773  }
11774  else
11775  candpos = -1;
11776  }
11777  else
11778  candpos = nvars - 1;
11779 
11780  /* check last coefficient for integrality */
11781  if( gcd > 1 && allcoefintegral && !redundant )
11782  {
11783  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11784  allcoefintegral = FALSE;
11785  }
11786 
11787  /* check for further necessary coefficient adjustments */
11788  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11789  {
11790  assert(offsetv + 1 < nvars);
11791  assert(0 <= candpos && candpos < nvars);
11792 
11793  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
11794  {
11795  SCIP_Bool notchangable = FALSE;
11796 
11797 #ifndef NDEBUG
11798  /* check integrality */
11799  for( w = offsetv + 1; w < nvars; ++w )
11800  {
11801  assert(SCIPisIntegral(scip, vals[w]));
11802  }
11803 #endif
11804 
11805  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11806  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11807  {
11808  /* determine the remainder of the side and the gcd */
11809  if( hasrhs )
11810  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11811  else
11812  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11813  assert(rest >= 0);
11814  assert(rest < gcd);
11815 
11816  /* determine the remainder of the coefficient candidate and the gcd */
11817  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11818  assert(restcoef >= 1);
11819  assert(restcoef < gcd);
11820 
11821  if( hasrhs )
11822  {
11823  /* calculate new coefficient */
11824  if( restcoef > rest )
11825  newcoef = vals[candpos] - restcoef + gcd;
11826  else
11827  newcoef = vals[candpos] - restcoef;
11828  }
11829  else
11830  {
11831  /* calculate new coefficient */
11832  if( rest == 0 || restcoef < rest )
11833  newcoef = vals[candpos] - restcoef;
11834  else
11835  newcoef = vals[candpos] - restcoef + gcd;
11836  }
11837 
11838 
11839  /* done */
11840 
11841  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11842  * another with the big coefficient was set to 1
11843  */
11844  if( hasrhs && SCIPisZero(scip, newcoef) )
11845  {
11846  notchangable = TRUE;
11847  }
11848  else if( SCIPisZero(scip, newcoef) )
11849  {
11850  /* delete old redundant coefficient */
11851  SCIP_CALL( delCoefPos(scip, cons, candpos) );
11852  ++(*nchgcoefs);
11853  }
11854  else
11855  {
11856  /* replace old with new coefficient */
11857  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11858  ++(*nchgcoefs);
11859  }
11860  }
11861  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11862  {
11863  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11864  }
11865 
11866  /* correct side and big coefficients */
11867  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11868  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11869  {
11870  if( haslhs )
11871  {
11872  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11873 
11874  SCIP_CALL( chgLhs(scip, cons, newcoef) );
11875  ++(*nchgsides);
11876  }
11877  else
11878  {
11879  assert(hasrhs);
11880  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
11881 
11882  SCIP_CALL( chgRhs(scip, cons, newcoef) );
11883  ++(*nchgsides);
11884  }
11885 
11886  /* correct coefficients up front */
11887  for( w = offsetv; w >= 0; --w )
11888  {
11889  assert(vals[w] > 0);
11890 
11891  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
11892  }
11893  (*nchgcoefs) += (offsetv + 1);
11894  }
11895 
11896  if( !notchangable )
11897  {
11898  /* normalize constraint */
11899  SCIP_CALL( normalizeCons(scip, cons) );
11900  assert(vars == consdata->vars);
11901  assert(vals == consdata->vals);
11902 
11903  /* get new constraint data */
11904  nvars = consdata->nvars;
11905  assert(nvars >= 2);
11906 
11907  SCIPdebugPrintCons(scip, cons, NULL);
11908 
11909  lhs = consdata->lhs;
11910  rhs = consdata->rhs;
11911  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11912  assert(!haslhs || !SCIPisNegative(scip, lhs));
11913  }
11914  }
11915  }
11916  }
11917 
11918  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
11919  /* no continuous variables are left over */
11920  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
11921  return SCIP_OKAY;
11922 
11923  onlybin = TRUE;
11924  allcoefintegral = TRUE;
11925  /* check if all variables are of binary type */
11926  for( v = nvars - 1; v >= 0; --v )
11927  {
11928  if( !SCIPvarIsBinary(vars[v]) )
11929  onlybin = FALSE;
11930  if( !SCIPisIntegral(scip, vals[v]) )
11931  allcoefintegral = FALSE;
11932  }
11933 
11934  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
11935  * hand side or bigger than the left hand side respectively, so we can make all of them integral
11936  *
11937  * @todo there are some steps missing ....
11938  */
11939  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
11940  {
11941  SCIP_Real val;
11942  SCIP_Real newval;
11943  SCIP_Real frac = 0.0;
11944  SCIP_Bool found = FALSE;
11945 
11946  if( hasrhs )
11947  {
11948  if( allcoefintegral )
11949  {
11950  /* replace old with new right hand side */
11951  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
11952  ++(*nchgsides);
11953  }
11954  else
11955  {
11956  siderest = rhs - SCIPfloor(scip, rhs);
11957 
11958  /* try to round down all non-integral coefficients */
11959  for( v = nvars - 1; v >= 0; --v )
11960  {
11961  val = vals[v];
11962 
11963  /* add up all possible fractional parts */
11964  if( !SCIPisIntegral(scip, val) )
11965  {
11966  lb = SCIPvarGetLbGlobal(vars[v]);
11967  ub = SCIPvarGetUbGlobal(vars[v]);
11968 
11969  /* at least one bound need to be at zero */
11970  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
11971  return SCIP_OKAY;
11972 
11973  /* swap bounds for 'standard' form */
11974  if( !SCIPisFeasZero(scip, lb) )
11975  {
11976  ub = lb;
11977  val *= -1;
11978  }
11979 
11980  found = TRUE;
11981 
11982  frac += (val - SCIPfloor(scip, val)) * ub;
11983 
11984  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
11985  *
11986  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
11987  * x3, x4 set to 1 would be infeasible but feasible after flooring
11988  */
11989  if( SCIPisGT(scip, frac, siderest) )
11990  return SCIP_OKAY;
11991  }
11992  }
11993  assert(v == -1);
11994 
11995  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
11996 
11997  /* round rhs and coefficients to integral values */
11998  if( found )
11999  {
12000  for( v = nvars - 1; v >= 0; --v )
12001  {
12002  val = vals[v];
12003 
12004  /* add the whole fractional part */
12005  if( !SCIPisIntegral(scip, val) )
12006  {
12007  lb = SCIPvarGetLbGlobal(vars[v]);
12008 
12009  if( SCIPisFeasZero(scip, lb) )
12010  newval = SCIPfloor(scip, val);
12011  else
12012  newval = SCIPceil(scip, val);
12013 
12014  if( SCIPisZero(scip, newval) )
12015  {
12016  /* delete old redundant coefficient */
12017  SCIP_CALL( delCoefPos(scip, cons, v) );
12018  ++(*nchgcoefs);
12019  }
12020  else
12021  {
12022  /* replace old with new coefficient */
12023  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12024  ++(*nchgcoefs);
12025  }
12026  }
12027  }
12028  }
12029 
12030  /* replace old with new right hand side */
12031  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12032  ++(*nchgsides);
12033  }
12034  }
12035  else
12036  {
12037  if( allcoefintegral )
12038  {
12039  /* replace old with new left hand side */
12040  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12041  ++(*nchgsides);
12042  }
12043  else
12044  {
12045  /* cannot floor left hand side to zero */
12046  if( SCIPisLT(scip, lhs, 1.0) )
12047  return SCIP_OKAY;
12048 
12049  siderest = lhs - SCIPfloor(scip, lhs);
12050 
12051  /* try to round down all non-integral coefficients */
12052  for( v = nvars - 1; v >= 0; --v )
12053  {
12054  val = vals[v];
12055 
12056  /* add up all possible fractional parts */
12057  if( !SCIPisIntegral(scip, val) )
12058  {
12059  lb = SCIPvarGetLbGlobal(vars[v]);
12060  ub = SCIPvarGetUbGlobal(vars[v]);
12061 
12062  /* at least one bound need to be at zero */
12063  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12064  return SCIP_OKAY;
12065 
12066  /* swap bounds for 'standard' form */
12067  if( !SCIPisFeasZero(scip, lb) )
12068  {
12069  ub = lb;
12070  val *= -1;
12071  }
12072 
12073  /* cannot floor to zero */
12074  if( SCIPisLT(scip, val, 1.0) )
12075  return SCIP_OKAY;
12076 
12077  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12078  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12079  return SCIP_OKAY;
12080 
12081  found = TRUE;
12082 
12083  frac += (val - SCIPfloor(scip, val)) * ub;
12084 
12085  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12086  * fractional parts of the variables, we cannot tighten the coefficients
12087  *
12088  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12089  * x2-x4 set to 1 would be feasible but not after flooring
12090  */
12091  if( SCIPisGE(scip, frac, 1 + siderest) )
12092  return SCIP_OKAY;
12093  }
12094  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12095  else
12096  return SCIP_OKAY;
12097  }
12098  assert(v == -1);
12099 
12100  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12101 
12102  /* round lhs and coefficients to integral values */
12103  if( found )
12104  {
12105  for( v = nvars - 1; v >= 0; --v )
12106  {
12107  val = vals[v];
12108 
12109  /* add the whole fractional part */
12110  if( !SCIPisIntegral(scip, val) )
12111  {
12112  lb = SCIPvarGetLbGlobal(vars[v]);
12113 
12114  if( SCIPisFeasZero(scip, lb) )
12115  newval = SCIPfloor(scip, val);
12116  else
12117  newval = SCIPceil(scip, val);
12118 
12119  if( SCIPisZero(scip, newval) )
12120  {
12121  /* delete old redundant coefficient */
12122  SCIP_CALL( delCoefPos(scip, cons, v) );
12123  ++(*nchgcoefs);
12124  }
12125  else
12126  {
12127  /* replace old with new coefficient */
12128  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12129  ++(*nchgcoefs);
12130  }
12131  }
12132  }
12133  }
12134 
12135  /* replace old with new left hand side */
12136  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12137  ++(*nchgsides);
12138  }
12139  }
12140 
12141  /* normalize constraint */
12142  SCIP_CALL( normalizeCons(scip, cons) );
12143  assert(vars == consdata->vars);
12144  assert(vals == consdata->vals);
12145 
12146  rhs = consdata->rhs;
12147  lhs = consdata->lhs;
12148 
12149  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12150  assert(!haslhs || !SCIPisNegative(scip, lhs));
12151 
12152  SCIPdebugPrintCons(scip, cons, NULL);
12153 
12154  nvars = consdata->nvars;
12155  if( nvars < 2 )
12156  return SCIP_OKAY;
12157 
12158  allcoefintegral = TRUE;
12159 #ifndef NDEBUG
12160  /* debug check if all coefficients are really integral */
12161  for( v = nvars - 1; v >= 0; --v )
12162  assert(SCIPisIntegral(scip, vals[v]));
12163 #endif
12164  }
12165 
12166  /* @todo following can also work on non integral coefficients, need more investigation */
12167  /* only check constraints with integral coefficients on all integral variables */
12168  if( !allcoefintegral )
12169  return SCIP_OKAY;
12170 
12171  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12172  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12173  return SCIP_OKAY;
12174 
12175  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12176  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12177  return SCIP_OKAY;
12178 
12179  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12180  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12181  return SCIP_OKAY;
12182 
12183  assert(nvars >= 2);
12184 
12185  /* start gcd procedure for all variables */
12186  do
12187  {
12188  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12189  SCIPdebug( oldnchgsides = *nchgsides; )
12190 
12191  /* stop if we have two coeffcients which are one in absolute value */
12192  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12193  return SCIP_OKAY;
12194 
12195  gcd = -1;
12196 
12197  /* calculate greatest common divisor over all integer variables */
12198  if( !onlybin )
12199  {
12200  foundbin = -1;
12201 
12202  for( v = nvars - 1; v >= 0; --v )
12203  {
12204  assert(!SCIPisZero(scip, vals[v]));
12205  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12206 
12207  if( SCIPvarIsBinary(vars[v]) )
12208  {
12209  if( foundbin == -1 )
12210  foundbin = v;
12211  continue;
12212  }
12213 
12214  absval = REALABS(vals[v]);
12215  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12216  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12217  */
12218  assert(SCIPisFeasIntegral(scip, absval));
12219 
12220  if( gcd == -1 )
12221  {
12222  gcd = (SCIP_Longint)(absval + feastol);
12223  assert(gcd >= 1);
12224  }
12225  else
12226  {
12227  /* calculate greatest common divisor for all general variables */
12228  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12229  }
12230  if( gcd == 1 )
12231  break;
12232  }
12233  }
12234  else
12235  foundbin = nvars - 1;
12236 
12237  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12238  if( gcd == 1 || foundbin == -1)
12239  return SCIP_OKAY;
12240 
12241  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12242 
12243  candpos = -1;
12244  candpos2 = -1;
12245 
12246  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12247  * change the coefficient
12248  */
12249  for( v = foundbin; v >= 0; --v )
12250  {
12251  if( onlybin || SCIPvarIsBinary(vars[v]) )
12252  {
12253  absval = REALABS(vals[v]);
12254  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12255  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12256  */
12257  assert(SCIPisFeasIntegral(scip, absval));
12258 
12259  oldgcd = gcd;
12260 
12261  if( gcd == -1 )
12262  {
12263  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12264  assert(gcd >= 1);
12265  }
12266  else
12267  {
12268  /* calculate greatest common divisor for all general and binary variables */
12269  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12270  }
12271 
12272  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12273  * can terminate
12274  */
12275  if( gcd == 1 )
12276  {
12277  /* found candidate */
12278  if( candpos == -1 )
12279  {
12280  gcd = oldgcd;
12281  candpos = v;
12282 
12283  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12284  * the coefficient change
12285  */
12286  if( onlybin && v == foundbin - 1 )
12287  candpos2 = foundbin;
12288  }
12289  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12290  else
12291  {
12292  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12293  {
12294  assert(candpos2 == nvars - 1);
12295 
12296  /* take new candidates */
12297  candpos = candpos2;
12298 
12299  /* recalculate gcd from scratch */
12300  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12301  assert(gcd >= 1);
12302 
12303  /* calculate greatest common divisor for all general and binary variables */
12304  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12305  if( gcd == 1 )
12306  return SCIP_OKAY;
12307  }
12308  else
12309  /* cannot determine a possible coefficient for reduction */
12310  return SCIP_OKAY;
12311  }
12312  }
12313  }
12314  }
12315  assert(gcd >= 2);
12316 
12317  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12318  * further
12319  */
12320  assert(candpos >= 0 && candpos < nvars);
12321 
12322  /* all variables and all coefficients are integral, so the side should be too */
12323  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12324 
12325  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12326  * @see normalizeCons()
12327  */
12328  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12329  assert(!haslhs || !SCIPisNegative(scip, lhs));
12330 
12331  /* determine the remainder of the side and the gcd */
12332  if( hasrhs )
12333  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12334  else
12335  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12336  assert(rest >= 0);
12337  assert(rest < gcd);
12338 
12339  /* determine the remainder of the coefficient candidate and the gcd */
12340  if( vals[candpos] < 0 )
12341  {
12342  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12343  assert(restcoef <= -1);
12344  restcoef += gcd;
12345  }
12346  else
12347  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12348  assert(restcoef >= 1);
12349  assert(restcoef < gcd);
12350 
12351  if( hasrhs )
12352  {
12353  if( rest > 0 )
12354  {
12355  /* replace old with new right hand side */
12356  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12357  ++(*nchgsides);
12358  }
12359 
12360  /* calculate new coefficient */
12361  if( restcoef > rest )
12362  newcoef = vals[candpos] - restcoef + gcd;
12363  else
12364  newcoef = vals[candpos] - restcoef;
12365  }
12366  else
12367  {
12368  if( rest > 0 )
12369  {
12370  /* replace old with new left hand side */
12371  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12372  ++(*nchgsides);
12373  }
12374 
12375  /* calculate new coefficient */
12376  if( rest == 0 || restcoef < rest )
12377  newcoef = vals[candpos] - restcoef;
12378  else
12379  newcoef = vals[candpos] - restcoef + gcd;
12380  }
12381  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12382 
12383  SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12384 
12385  if( SCIPisZero(scip, newcoef) )
12386  {
12387  /* delete redundant coefficient */
12388  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12389  }
12390  else
12391  {
12392  /* replace old with new coefficient */
12393  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12394  }
12395  ++(*nchgcoefs);
12396 
12397  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12398  SCIP_CALL( normalizeCons(scip, cons) );
12399  assert(vars == consdata->vars);
12400  assert(vals == consdata->vals);
12401 
12402  SCIPdebugPrintCons(scip, cons, NULL);
12403 
12404  rhs = consdata->rhs;
12405  lhs = consdata->lhs;
12406  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12407  assert(!haslhs || !SCIPisNegative(scip, lhs));
12408 
12409  nvars = consdata->nvars;
12410 
12411  SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12412  }
12413  while( nvars >= 2 );
12414 
12415  return SCIP_OKAY;
12416 }
12417 
12418 
12419 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12420  * cons0 := a * cons0 + b * cons1,
12421  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12422  * for numerical stability, we will only accept integral a and b;
12423  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12424  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12425  */
12426 static
12428  SCIP* scip, /**< SCIP data structure */
12429  SCIP_CONS* cons0, /**< (in)equality to modify */
12430  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12431  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12432  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12433  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12434  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12435  int nvarscommon, /**< number of variables, that appear in both constraints */
12436  int commonidxweight, /**< variable weight sum of common variables */
12437  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12438  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12439  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12440  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12441  SCIP_Bool* aggregated /**< pointer to store whether an aggregation was made */
12442  )
12443 {
12444  SCIP_CONSDATA* consdata0;
12445  SCIP_CONSDATA* consdata1;
12446  SCIP_Real a;
12447  SCIP_Real b;
12448  SCIP_Real aggrcoef;
12449  SCIP_Real scalarsum;
12450  SCIP_Real bestscalarsum;
12451  SCIP_Bool betterscalarsum;
12452  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12453  int varweight;
12454  int nvars;
12455  int bestvarweight;
12456  int bestnvars;
12457  int bestv;
12458  int v;
12459  int i;
12460 
12461  assert(scip != NULL);
12462  assert(cons0 != NULL);
12463  assert(cons1 != NULL);
12464  assert(commonidx0 != NULL);
12465  assert(commonidx1 != NULL);
12466  assert(diffidx0minus1 != NULL);
12467  assert(diffidx1minus0 != NULL);
12468  assert(nvarscommon >= 1);
12469  assert(commonidxweight >= nvarscommon);
12470  assert(nchgcoefs != NULL);
12471  assert(aggregated != NULL);
12472 
12473  assert(SCIPconsIsActive(cons0));
12474  assert(SCIPconsIsActive(cons1));
12475 
12476  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12477 
12478  /* cons0 is an (in)equality */
12479  consdata0 = SCIPconsGetData(cons0);
12480  assert(consdata0 != NULL);
12481  assert(consdata0->nvars >= 1);
12482  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12483  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12484 
12485  /* cons1 is an equality */
12486  consdata1 = SCIPconsGetData(cons1);
12487  assert(consdata1 != NULL);
12488  assert(consdata1->nvars >= 1);
12489  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12490  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12491 
12492  *aggregated = FALSE;
12493 
12494  /* search for the best common variable such that
12495  * val1[var] * consdata0 - val0[var] * consdata1
12496  * has least weighted number of variables
12497  */
12498  bestvarweight = commonidxweight + diffidx0minus1weight;
12499  bestnvars = consdata0->nvars;
12500  bestv = -1;
12501  bestscalarsum = 0.0;
12502  commonvarlindependent = TRUE;
12503  for( v = 0; v < nvarscommon; ++v )
12504  {
12505  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12506  a = consdata1->vals[commonidx1[v]];
12507  b = -consdata0->vals[commonidx0[v]];
12508 
12509  /* only try aggregation, if coefficients are integral (numerical stability) */
12510  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12511  {
12512  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12513  varweight = diffidx0minus1weight + diffidx1minus0weight;
12514  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12515  scalarsum = REALABS(a) + REALABS(b);
12516  betterscalarsum = (scalarsum < bestscalarsum);
12517  for( i = 0; i < nvarscommon
12518  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12519  {
12520  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12521  if( !SCIPisZero(scip, aggrcoef) )
12522  {
12523  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12524  nvars++;
12525  }
12526  }
12527  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12528  {
12529  bestv = v;
12530  bestvarweight = varweight;
12531  bestnvars = nvars;
12532  bestscalarsum = scalarsum;
12533  }
12534  }
12535 
12536  /* update commonvarlindependent flag, if still TRUE:
12537  * 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
12538  */
12539  if( commonvarlindependent && v > 0 )
12540  commonvarlindependent = SCIPisEQ(scip,
12541  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12542  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12543  }
12544 
12545  /* if better aggregation was found, create new constraint and delete old one */
12546  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12547  {
12548  SCIP_CONS* newcons;
12549  SCIP_CONSDATA* newconsdata;
12550  SCIP_VAR** newvars;
12551  SCIP_Real* newvals;
12552  SCIP_Real newlhs;
12553  SCIP_Real newrhs;
12554  int newnvars;
12555 
12556  if( bestv != -1 )
12557  {
12558  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12559  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12560  {
12561  a = consdata1->vals[commonidx1[bestv]];
12562  b = -consdata0->vals[commonidx0[bestv]];
12563  }
12564  else
12565  {
12566  a = -consdata1->vals[commonidx1[bestv]];
12567  b = consdata0->vals[commonidx0[bestv]];
12568  }
12569  assert(SCIPisIntegral(scip, a));
12570  assert(SCIPisPositive(scip, a));
12571  assert(SCIPisIntegral(scip, b));
12572  assert(!SCIPisZero(scip, b));
12573  }
12574  else
12575  {
12576  assert(commonvarlindependent);
12577  if( consdata1->vals[commonidx1[0]] > 0.0 )
12578  {
12579  a = consdata1->vals[commonidx1[0]];
12580  b = -consdata0->vals[commonidx0[0]];
12581  }
12582  else
12583  {
12584  a = -consdata1->vals[commonidx1[0]];
12585  b = consdata0->vals[commonidx0[0]];
12586  }
12587  assert(SCIPisPositive(scip, a));
12588  assert(!SCIPisZero(scip, b));
12589 
12590  /* if a/b is integral, then we can easily choose integer multipliers */
12591  if( SCIPisIntegral(scip, a/b) )
12592  {
12593  if( a/b > 0 )
12594  {
12595  a /= b;
12596  b = 1.0;
12597  }
12598  else
12599  {
12600  a /= -b;
12601  b = -1.0;
12602  }
12603  }
12604 
12605  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12606  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12607  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12608  }
12609 
12610  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12611  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12612  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12613  SCIPdebugPrintCons(scip, cons0, NULL);
12614  SCIPdebugPrintCons(scip, cons1, NULL);
12615 
12616  /* get temporary memory for creating the new linear constraint */
12617  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12618  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12619 
12620  /* calculate the common coefficients, if we have not recognized linear dependency */
12621  newnvars = 0;
12622  if( !commonvarlindependent )
12623  {
12624  for( i = 0; i < nvarscommon; ++i )
12625  {
12626  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12627  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12628 
12629  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12630  if( !SCIPisZero(scip, aggrcoef) )
12631  {
12632  assert(newnvars < bestnvars);
12633  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12634  newvals[newnvars] = aggrcoef;
12635  newnvars++;
12636  }
12637  }
12638  }
12639  else
12640  {
12641  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12642 #ifndef NDEBUG
12643  for( i = 0; i < nvarscommon; ++i )
12644  {
12645  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12646  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12647 
12648  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12649  assert(SCIPisZero(scip, aggrcoef));
12650  }
12651 #endif
12652  }
12653 
12654  /* calculate the coefficients appearing in cons0 but not in cons1 */
12655  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12656  {
12657  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12658 
12659  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12660  assert(!SCIPisZero(scip, aggrcoef));
12661  assert(newnvars < bestnvars);
12662  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12663  newvals[newnvars] = aggrcoef;
12664  newnvars++;
12665  }
12666 
12667  /* calculate the coefficients appearing in cons1 but not in cons0 */
12668  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12669  {
12670  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12671 
12672  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12673  assert(!SCIPisZero(scip, aggrcoef));
12674  assert(newnvars < bestnvars);
12675  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12676  newvals[newnvars] = aggrcoef;
12677  newnvars++;
12678  }
12679  assert(newnvars == bestnvars);
12680 
12681  /* calculate the new left and right hand side of the (in)equality */
12682  assert(!SCIPisInfinity(scip, -consdata1->lhs));
12683  assert(!SCIPisInfinity(scip, consdata1->rhs));
12684  if( SCIPisInfinity(scip, -consdata0->lhs) )
12685  newlhs = -SCIPinfinity(scip);
12686  else
12687  newlhs = a * consdata0->lhs + b * consdata1->lhs;
12688  if( SCIPisInfinity(scip, consdata0->rhs) )
12689  newrhs = SCIPinfinity(scip);
12690  else
12691  newrhs = a * consdata0->rhs + b * consdata1->rhs;
12692 
12693  /* create the new linear constraint */
12694  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12696  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12697  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12699 
12700  newconsdata = SCIPconsGetData(newcons);
12701  assert(newconsdata != NULL);
12702 
12703  /* copy the upgraded flag from the old cons0 to the new constraint */
12704  newconsdata->upgraded = consdata0->upgraded;
12705 
12706  /* normalize the new constraint */
12707  SCIP_CALL( normalizeCons(scip, newcons) );
12708 
12709  /* check, if we really want to use the new constraint instead of the old one:
12710  * use the new one, if the maximum norm doesn't grow too much
12711  */
12712  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12713  {
12714  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12715  SCIPdebugPrintCons(scip, newcons, NULL);
12716 
12717  /* update the statistics: we changed all coefficients */
12718  if( !consdata0->upgraded )
12719  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12720  *aggregated = TRUE;
12721 
12722  /* delete the old constraint, and add the new linear constraint to the problem */
12723  SCIP_CALL( SCIPdelCons(scip, cons0) );
12724  SCIP_CALL( SCIPaddCons(scip, newcons) );
12725  }
12726 
12727  /* release the new constraint */
12728  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12729 
12730  /* free temporary memory */
12731  SCIPfreeBufferArray(scip, &newvals);
12732  SCIPfreeBufferArray(scip, &newvars);
12733  }
12734 
12735  return SCIP_OKAY;
12736 }
12737 
12738 /** gets the key of the given element */
12739 static
12740 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12741 { /*lint --e{715}*/
12742  /* the key is the element itself */
12743  return elem;
12744 }
12745 
12746 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12747  * coefficients are either equal or negated
12748  */
12749 static
12750 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12751 {
12752  SCIP* scip;
12753  SCIP_CONSDATA* consdata1;
12754  SCIP_CONSDATA* consdata2;
12755  SCIP_Real cons1scale;
12756  SCIP_Real cons2scale;
12757  int i;
12758 
12759  assert(key1 != NULL);
12760  assert(key2 != NULL);
12761  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12762  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12763  assert(consdata1->sorted);
12764  assert(consdata2->sorted);
12765 
12766  scip = (SCIP*)userptr;
12767  assert(scip != NULL);
12768 
12769  /* if it is the same constraint we dont need to check anything */
12770  if( key1 == key2 )
12771  return TRUE;
12772 
12773  /* checks trivial case */
12774  if( consdata1->nvars != consdata2->nvars )
12775  return FALSE;
12776 
12777  /* tests if variables are equal */
12778  for( i = 0; i < consdata1->nvars; ++i )
12779  {
12780  if( consdata1->vars[i] != consdata2->vars[i] )
12781  {
12782  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12783  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12784  return FALSE;
12785  }
12786  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12787  }
12788 
12789  /* compute scale before comparing coefficients of constraints */
12790  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
12791  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
12792 
12793  /* tests if coefficients are equal with the computed scale */
12794  for( i = 0; i < consdata1->nvars; ++i )
12795  {
12796  SCIP_Real val1;
12797  SCIP_Real val2;
12798 
12799  val1 = consdata1->vals[i] * cons1scale;
12800  val2 = consdata2->vals[i] * cons2scale;
12801 
12802  if( !SCIPisEQ(scip, val1, val2) )
12803  return FALSE;
12804  }
12805 
12806  return TRUE;
12807 }
12808 
12809 /** returns the hash value of the key */
12810 static
12811 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12812 {
12813  SCIP_CONSDATA* consdata;
12814  int minidx;
12815  int mididx;
12816  int maxidx;
12817  SCIP_Real scale;
12818 #ifndef NDEBUG
12819  SCIP* scip;
12820 
12821  scip = (SCIP*)userptr;
12822  assert(scip != NULL);
12823 #endif
12824 
12825  assert(key != NULL);
12826  consdata = SCIPconsGetData((SCIP_CONS*)key);
12827  assert(consdata != NULL);
12828  assert(consdata->nvars > 0);
12829 
12830  assert(consdata->sorted);
12831 
12832  minidx = SCIPvarGetIndex(consdata->vars[0]);
12833  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12834  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12835  assert(minidx >= 0 && minidx <= maxidx);
12836  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
12837 
12838  /* using only the variable indices as hash, since the values are compared by epsilon */
12839  return SCIPhashFour(consdata->nvars,
12840  SCIPcombineTwoInt(minidx, SCIPrealHashCode(consdata->vals[0] * scale)),
12841  SCIPcombineTwoInt(mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale)),
12842  SCIPcombineTwoInt(maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale))); /*lint !e571*/
12843 }
12844 
12845 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12846  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12847  */
12848 static
12849 unsigned int getParallelConsKey(
12850  SCIP_CONS* cons /**< linear constraint */
12851  )
12852 {
12853  SCIP_CONSDATA* consdata;
12854 
12855  assert(cons != NULL);
12856 
12857  consdata = SCIPconsGetData(cons);
12858  assert(consdata != NULL);
12859 
12860  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
12861 }
12862 
12863 /** updates the hashtable such that out of all constraints in the hashtable that are detected
12864  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
12865  * and all others are removed from the hashtable and stored in the given array
12866  */
12867 static
12869  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
12870  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
12871  * upon return will contain the constraint that should be kept */
12872  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
12873  * these constraints where removed from the hashtable */
12874  int* nparallelconss /**< pointer to return number of parallel constraints */
12875  )
12876 {
12877  SCIP_CONS* parallelcons;
12878  unsigned int querykey;
12879 
12880  *nparallelconss = 0;
12881  querykey = getParallelConsKey(*querycons);
12882 
12883  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
12884  {
12885  unsigned int conskey = getParallelConsKey(parallelcons);
12886 
12887  if( conskey < querykey )
12888  {
12889  parallelconss[(*nparallelconss)++] = *querycons;
12890  *querycons = parallelcons;
12891  querykey = conskey;
12892  }
12893  else
12894  {
12895  parallelconss[(*nparallelconss)++] = parallelcons;
12896  }
12897 
12898  /* if the constraint that just came out of the hash table is the one that is kept,
12899  * we do not need to look into the hashtable again, since the invariant is that
12900  * in the hashtable only pair-wise non-parallel constraints are contained.
12901  * For the original querycons, however, multiple constraints that compare equal (=parallel)
12902  * could be contained due to non-transitivity of the equality comparison.
12903  * Also we can return immediately, since parallelcons is already contained in the
12904  * hashtable and we do not need to remove and reinsert it.
12905  */
12906  if( *querycons == parallelcons )
12907  return SCIP_OKAY;
12908 
12909  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
12910  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
12911  }
12912 
12913  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
12914  * comnpares equal to querycons at this point
12915  */
12916 #ifndef NDEBUG
12917  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
12918 #else
12919  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
12920 #endif
12921 
12922  return SCIP_OKAY;
12923 }
12924 
12925 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
12926  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
12927  */
12928 static
12930  SCIP* scip, /**< SCIP data structure */
12931  BMS_BLKMEM* blkmem, /**< block memory */
12932  SCIP_CONS** conss, /**< constraint set */
12933  int nconss, /**< number of constraints in constraint set */
12934  int* firstchange, /**< pointer to store first changed constraint */
12935  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
12936  int* ndelconss, /**< pointer to count number of deleted constraints */
12937  int* nchgsides /**< pointer to count number of changed left/right hand sides */
12938  )
12939 {
12940  SCIP_HASHTABLE* hashtable;
12941  SCIP_CONS** parallelconss;
12942  int nparallelconss;
12943  int hashtablesize;
12944  int c;
12945 
12946  assert(scip != NULL);
12947  assert(blkmem != NULL);
12948  assert(conss != NULL);
12949  assert(firstchange != NULL);
12950  assert(cutoff != NULL);
12951  assert(ndelconss != NULL);
12952  assert(nchgsides != NULL);
12953 
12954  /* create a hash table for the constraint set */
12955  hashtablesize = nconss;
12956  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
12957  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
12958 
12959  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
12960 
12961  /* check all constraints in the given set for redundancy */
12962  for( c = 0; c < nconss; ++c )
12963  {
12964  SCIP_CONS* cons0;
12965  SCIP_CONSDATA* consdata0;
12966 
12967  cons0 = conss[c];
12968 
12969  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
12970  continue;
12971 
12972  /* check for interuption */
12973  if( c % 1000 == 0 && SCIPisStopped(scip) )
12974  break;
12975 
12976  /* sorts the constraint */
12977  consdata0 = SCIPconsGetData(cons0);
12978  assert(consdata0 != NULL);
12979  SCIP_CALL( consdataSort(scip, consdata0) );
12980  assert(consdata0->sorted);
12981 
12982  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
12983  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
12984  * first variable is positive
12985  * Also inserts cons0 into the hashtable.
12986  */
12987  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
12988 
12989  if( nparallelconss != 0 )
12990  {
12991  SCIP_Real lhs;
12992  SCIP_Real rhs;
12993 
12994  int i;
12995 
12996  /* cons0 may have been changed in retrieveParallelConstraints() */
12997  consdata0 = SCIPconsGetData(cons0);
12998 
12999  lhs = consdata0->lhs;
13000  rhs = consdata0->rhs;
13001 
13002  for( i = 0; i < nparallelconss; ++i )
13003  {
13004  SCIP_CONS* consdel;
13005  SCIP_CONSDATA* consdatadel;
13006  SCIP_Real scale;
13007 
13008  consdel = parallelconss[i];
13009  consdatadel = SCIPconsGetData(consdel);
13010 
13011  assert(SCIPconsIsActive(consdel));
13012  assert(!SCIPconsIsModifiable(consdel));
13013 
13014  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13015  * delete old constraints afterwards
13016  */
13017  assert(consdatadel != NULL);
13018  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13019 
13020  assert(consdatadel->sorted);
13021  assert(consdata0->vars[0] == consdatadel->vars[0]);
13022 
13023  scale = consdata0->vals[0] / consdatadel->vals[0];
13024  assert(scale != 0.0);
13025 
13026  /* in debug mode, check that all coefficients are equal with respect to epsilon
13027  * if the constraints are in equilibrium scale
13028  */
13029 #ifndef NDEBUG
13030  {
13031  int k;
13032  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13033  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13034 
13035  for( k = 0; k < consdata0->nvars; ++k )
13036  {
13037  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13038  }
13039  }
13040 #endif
13041 
13042  if( scale > 0.0 )
13043  {
13044  /* the coefficients of both constraints are parallel with a positive scale */
13045  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13046  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13047  SCIPdebugPrintCons(scip, cons0, NULL);
13048  SCIPdebugPrintCons(scip, consdel, NULL);
13049 
13050  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13051  lhs = MAX(scale * consdatadel->lhs, lhs);
13052 
13053  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13054  rhs = MIN(scale * consdatadel->rhs, rhs);
13055  }
13056  else
13057  {
13058  /* the coefficients of both rows are negations */
13059  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13060  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13061  SCIPdebugPrintCons(scip, cons0, NULL);
13062  SCIPdebugPrintCons(scip, consdel, NULL);
13063 
13064  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13065  lhs = MAX(scale * consdatadel->rhs, lhs);
13066 
13067  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13068  rhs = MIN(scale * consdatadel->lhs, rhs);
13069  }
13070 
13071  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13072  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13073 
13074  /* delete consdel */
13075  assert( ! consdata0->upgraded || consdatadel->upgraded );
13076  SCIP_CALL( SCIPdelCons(scip, consdel) );
13077  if( !consdatadel->upgraded )
13078  (*ndelconss)++;
13079  }
13080 
13081  if( SCIPisFeasLT(scip, rhs, lhs) )
13082  {
13083  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13084  *cutoff = TRUE;
13085  break;
13086  }
13087 
13088  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13089  if( lhs > rhs )
13090  {
13091  rhs = (lhs + rhs)/2;
13092  lhs = rhs;
13093  }
13094 
13095  /* update lhs and rhs of cons0 */
13096  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13097  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13098 
13099  /* update the first changed constraint to begin the next aggregation round with */
13100  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13101  *firstchange = SCIPconsGetPos(cons0);
13102 
13103  assert(SCIPconsIsActive(cons0));
13104  }
13105  }
13106 #ifdef SCIP_MORE_DEBUG
13107  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13109 #endif
13110 
13111  SCIPfreeBufferArray(scip, &parallelconss);
13112 
13113  /* free hash table */
13114  SCIPhashtableFree(&hashtable);
13115 
13116  return SCIP_OKAY;
13117 }
13118 
13119 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13120  * and removes or changes constraint accordingly
13121  */
13122 static
13124  SCIP* scip, /**< SCIP data structure */
13125  SCIP_CONS** conss, /**< constraint set */
13126  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13127  int chkind, /**< index of constraint to check against all prior indices upto startind */
13128  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13129  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13130  int* ndelconss, /**< pointer to count number of deleted constraints */
13131  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13132  int* nchgcoefs /**< pointer to count number of changed coefficients */
13133  )
13134 {
13135  SCIP_CONS* cons0;
13136  SCIP_CONSDATA* consdata0;
13137  int* commonidx0;
13138  int* commonidx1;
13139  int* diffidx0minus1;
13140  int* diffidx1minus0;
13141  uint64_t possignature0;
13142  uint64_t negsignature0;
13143  SCIP_Bool cons0changed;
13144  SCIP_Bool cons0isequality;
13145  int diffidx1minus0size;
13146  int c;
13147  SCIP_Real cons0lhs;
13148  SCIP_Real cons0rhs;
13149  SCIP_Bool cons0upgraded;
13150 
13151  assert(scip != NULL);
13152  assert(conss != NULL);
13153  assert(firstchange <= chkind);
13154  assert(cutoff != NULL);
13155  assert(ndelconss != NULL);
13156  assert(nchgsides != NULL);
13157  assert(nchgcoefs != NULL);
13158 
13159  /* get the constraint to be checked against all prior constraints */
13160  cons0 = conss[chkind];
13161  assert(cons0 != NULL);
13162  assert(SCIPconsIsActive(cons0));
13163  assert(!SCIPconsIsModifiable(cons0));
13164 
13165  consdata0 = SCIPconsGetData(cons0);
13166  assert(consdata0 != NULL);
13167  assert(consdata0->nvars >= 1);
13168  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13169 
13170  /* sort the constraint */
13171  SCIP_CALL( consdataSort(scip, consdata0) );
13172 
13173  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13174  consdataCalcSignatures(consdata0);
13175  possignature0 = consdata0->possignature;
13176  negsignature0 = consdata0->negsignature;
13177 
13178  /* get temporary memory for indices of common variables */
13179  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13180  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13181  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13182  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13183  diffidx1minus0size = consdata0->nvars;
13184 
13185  cons0lhs = consdata0->lhs;
13186  cons0rhs = consdata0->rhs;
13187  cons0upgraded = consdata0->upgraded;
13188 
13189  /* check constraint against all prior constraints */
13190  cons0changed = consdata0->changed;
13191  consdata0->changed = FALSE;
13192  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13193  {
13194  SCIP_CONS* cons1;
13195  SCIP_CONSDATA* consdata1;
13196  uint64_t possignature1;
13197  uint64_t negsignature1;
13198  SCIP_Bool cons0dominateslhs;
13199  SCIP_Bool cons1dominateslhs;
13200  SCIP_Bool cons0dominatesrhs;
13201  SCIP_Bool cons1dominatesrhs;
13202  SCIP_Bool cons1isequality;
13203  SCIP_Bool coefsequal;
13204  SCIP_Bool coefsnegated;
13205  SCIP_Bool tryaggregation;
13206  int nvarscommon;
13207  int nvars0minus1;
13208  int nvars1minus0;
13209  int commonidxweight;
13210  int diffidx0minus1weight;
13211  int diffidx1minus0weight;
13212  int v0;
13213  int v1;
13214 
13215  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13216  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13217  assert(cons0upgraded == consdata0->upgraded);
13218 
13219  cons1 = conss[c];
13220 
13221  /* cons1 has become inactive during presolving of constraint pairs */
13222  if( cons1 == NULL )
13223  continue;
13224 
13225  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13226  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13227 
13228  consdata1 = SCIPconsGetData(cons1);
13229  assert(consdata1 != NULL);
13230 
13231  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13232  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13233  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13234 
13235  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13236  if( !cons0changed && !consdata1->changed )
13237  continue;
13238 
13239  /* if both constraints are already upgraded, skip the pair;
13240  * because changes on these constraints cannot be applied to the instance anymore */
13241  if( cons0upgraded && consdata1->upgraded )
13242  continue;
13243 
13244  assert(consdata1->nvars >= 1);
13245 
13246  /* sort the constraint */
13247  SCIP_CALL( consdataSort(scip, consdata1) );
13248 
13249  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13250  consdataCalcSignatures(consdata1);
13251  possignature1 = consdata1->possignature;
13252  negsignature1 = consdata1->negsignature;
13253 
13254  /* the signatures give a quick test to check for domination and equality of coefficients */
13255  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13256  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13257  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13258  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13259  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13260  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13261  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13262  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13263  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13264  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13265  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13266  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13267  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13268  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13269  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13270  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13271  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13272  && !coefsequal && !coefsnegated && !tryaggregation )
13273  continue;
13274 
13275  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13276  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13277  {
13278  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13279  diffidx1minus0size = consdata1->nvars;
13280  }
13281 
13282  /* check consdata0 against consdata1:
13283  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13284  * consdata0 dominates consdata1 w.r.t. left hand side
13285  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13286  * consdata0 dominates consdata1 w.r.t. right hand side
13287  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13288  * ranged row (or equality)
13289  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13290  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13291  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13292  * number of continuous and integer variables are preferred:
13293  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13294  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13295  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13296  * to be positive to not switch the sense of the (in)equality cons0
13297  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13298  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13299  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13300  * to be positive to not switch the sense of the (in)equality cons1
13301  */
13302 
13303  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13304  nvarscommon = 0;
13305  commonidxweight = 0;
13306  nvars0minus1 = 0;
13307  diffidx0minus1weight = 0;
13308  nvars1minus0 = 0;
13309  diffidx1minus0weight = 0;
13310  v0 = 0;
13311  v1 = 0;
13312  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13313  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13314  || coefsequal || coefsnegated || tryaggregation) )
13315  {
13316  SCIP_VAR* var;
13317  SCIP_Real val0;
13318  SCIP_Real val1;
13319  int varcmp;
13320 
13321  /* test, if variable appears in only one or in both constraints */
13322  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13323  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13324  else if( v0 < consdata0->nvars )
13325  varcmp = -1;
13326  else
13327  varcmp = +1;
13328 
13329  switch( varcmp )
13330  {
13331  case -1:
13332  /* variable doesn't appear in consdata1 */
13333  var = consdata0->vars[v0];
13334  val0 = consdata0->vals[v0];
13335  val1 = 0.0;
13336  if( tryaggregation )
13337  {
13338  diffidx0minus1[nvars0minus1] = v0;
13339  nvars0minus1++;
13340  diffidx0minus1weight += getVarWeight(var);
13341  }
13342  v0++;
13343  coefsequal = FALSE;
13344  coefsnegated = FALSE;
13345  break;
13346 
13347  case +1:
13348  /* variable doesn't appear in consdata0 */
13349  var = consdata1->vars[v1];
13350  val0 = 0.0;
13351  val1 = consdata1->vals[v1];
13352  if( tryaggregation )
13353  {
13354  diffidx1minus0[nvars1minus0] = v1;
13355  nvars1minus0++;
13356  diffidx1minus0weight += getVarWeight(var);
13357  }
13358  v1++;
13359  coefsequal = FALSE;
13360  coefsnegated = FALSE;
13361  break;
13362 
13363  case 0:
13364  /* variable appears in both constraints */
13365  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13366  var = consdata0->vars[v0];
13367  val0 = consdata0->vals[v0];
13368  val1 = consdata1->vals[v1];
13369  if( tryaggregation )
13370  {
13371  commonidx0[nvarscommon] = v0;
13372  commonidx1[nvarscommon] = v1;
13373  nvarscommon++;
13374  commonidxweight += getVarWeight(var);
13375  }
13376  v0++;
13377  v1++;
13378  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13379  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13380  break;
13381 
13382  default:
13383  SCIPerrorMessage("invalid comparison result\n");
13384  SCIPABORT();
13385  var = NULL;
13386  val0 = 0.0;
13387  val1 = 0.0;
13388  }
13389  assert(var != NULL);
13390 
13391  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13392  if( SCIPisGT(scip, val0, val1) )
13393  {
13394  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13395  {
13396  cons0dominatesrhs = FALSE;
13397  cons1dominateslhs = FALSE;
13398  }
13399  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13400  {
13401  cons0dominateslhs = FALSE;
13402  cons1dominatesrhs = FALSE;
13403  }
13404  }
13405  else if( SCIPisLT(scip, val0, val1) )
13406  {
13407  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13408  {
13409  cons0dominateslhs = FALSE;
13410  cons1dominatesrhs = FALSE;
13411  }
13412  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13413  {
13414  cons0dominatesrhs = FALSE;
13415  cons1dominateslhs = FALSE;
13416  }
13417  }
13418  }
13419 
13420  /* check for disaggregated ranged rows */
13421  if( coefsequal || coefsnegated )
13422  {
13423  SCIP_CONS* consstay;
13424  SCIP_CONS* consdel;
13425 #ifndef NDEBUG
13426  SCIP_CONSDATA* consdatastay;
13427 #endif
13428  SCIP_CONSDATA* consdatadel;
13429  SCIP_Real lhs;
13430  SCIP_Real rhs;
13431  int consinddel;
13432 
13433  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13434  * best left and right hand sides; delete the old constraints afterwards
13435  */
13436  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13437  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13438  SCIPdebugPrintCons(scip, cons0, NULL);
13439  SCIPdebugPrintCons(scip, cons1, NULL);
13440 
13441  if( coefsequal )
13442  {
13443  /* the coefficients of both rows are equal */
13444  lhs = MAX(consdata0->lhs, consdata1->lhs);
13445  rhs = MIN(consdata0->rhs, consdata1->rhs);
13446  }
13447  else
13448  {
13449  /* the coefficients of both rows are negations */
13450  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13451  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13452  }
13453  if( SCIPisFeasLT(scip, rhs, lhs) )
13454  {
13455  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13456  *cutoff = TRUE;
13457  break;
13458  }
13459 
13460  /* check which constraint has to stay;
13461  * changes applied to an upgraded constraint will not be considered in the instance */
13462  if( consdata0->upgraded )
13463  {
13464  assert(!consdata1->upgraded);
13465  consstay = cons1;
13466 #ifndef NDEBUG
13467  consdatastay = consdata1;
13468 #endif
13469 
13470  consdel = cons0;
13471  consdatadel = consdata0;
13472  consinddel = chkind;
13473  }
13474  else
13475  {
13476  consstay = cons0;
13477 #ifndef NDEBUG
13478  consdatastay = consdata0;
13479 #endif
13480 
13481  consdel = cons1;
13482  consdatadel = consdata1;
13483  consinddel = c;
13484  }
13485 
13486  /* update the sides of consstay */
13487  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13488  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13489  if( !consdata0->upgraded )
13490  {
13491  assert(consstay == cons0);
13492  cons0lhs = consdata0->lhs;
13493  cons0rhs = consdata0->rhs;
13494  }
13495 
13496  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13497  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13498 
13499  assert( !consdatastay->upgraded );
13500  /* delete consdel */
13501  SCIP_CALL( SCIPdelCons(scip, consdel) );
13502  conss[consinddel] = NULL;
13503  if( !consdatadel->upgraded )
13504  (*ndelconss)++;
13505  continue;
13506  }
13507 
13508  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13509  * redundant
13510  */
13511  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13512  {
13513  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13514  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13515  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13516  SCIPdebugPrintCons(scip, cons0, NULL);
13517  SCIPdebugPrintCons(scip, cons1, NULL);
13518 
13519  /* check for infeasibility */
13520  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13521  {
13522  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13523  *cutoff = TRUE;
13524  break;
13525  }
13526 
13527  /* remove redundant left hand side */
13528  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13529  {
13530  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13531  cons0lhs = consdata0->lhs;
13532  cons0isequality = FALSE;
13533  if( !consdata0->upgraded )
13534  {
13535  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13536  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13537 
13538  (*nchgsides)++;
13539  }
13540  }
13541  }
13542  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13543  {
13544  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13545  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13546  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13547  SCIPdebugPrintCons(scip, cons1, NULL);
13548  SCIPdebugPrintCons(scip, cons0, NULL);
13549 
13550  /* check for infeasibility */
13551  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13552  {
13553  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13554  *cutoff = TRUE;
13555  break;
13556  }
13557 
13558  /* remove redundant left hand side */
13559  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13560  {
13561  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13562  cons1isequality = FALSE;
13563  if( !consdata1->upgraded )
13564  {
13565  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13566  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13567 
13568  (*nchgsides)++;
13569  }
13570  }
13571  }
13572  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13573  {
13574  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13575  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13576  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13577  SCIPdebugPrintCons(scip, cons0, NULL);
13578  SCIPdebugPrintCons(scip, cons1, NULL);
13579 
13580  /* check for infeasibility */
13581  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13582  {
13583  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13584  *cutoff = TRUE;
13585  break;
13586  }
13587 
13588  /* remove redundant right hand side */
13589  if( !SCIPisInfinity(scip, consdata0->rhs) )
13590  {
13591  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13592  cons0rhs = consdata0->rhs;
13593  cons0isequality = FALSE;
13594  if( !consdata0->upgraded )
13595  {
13596  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13597  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13598 
13599  (*nchgsides)++;
13600  }
13601  }
13602  }
13603  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13604  {
13605  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13606  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13607  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13608  SCIPdebugPrintCons(scip, cons1, NULL);
13609  SCIPdebugPrintCons(scip, cons0, NULL);
13610 
13611  /* check for infeasibility */
13612  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13613  {
13614  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13615  *cutoff = TRUE;
13616  break;
13617  }
13618 
13619  /* remove redundant right hand side */
13620  if( !SCIPisInfinity(scip, consdata1->rhs) )
13621  {
13622  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13623  cons1isequality = FALSE;
13624  if( !consdata1->upgraded )
13625  {
13626  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13627  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13628 
13629  (*nchgsides)++;
13630  }
13631  }
13632  }
13633 
13634  /* check for now redundant constraints */
13635  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13636  {
13637  /* consdata0 became redundant */
13638  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13639  SCIP_CALL( SCIPdelCons(scip, cons0) );
13640  conss[chkind] = NULL;
13641  if( !consdata0->upgraded )
13642  {
13643  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13644  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13645 
13646  (*ndelconss)++;
13647  }
13648  continue;
13649  }
13650  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13651  {
13652  /* consdata1 became redundant */
13653  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13654  SCIP_CALL( SCIPdelCons(scip, cons1) );
13655  conss[c] = NULL;
13656  if( !consdata1->upgraded )
13657  {
13658  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13659  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13660 
13661  (*ndelconss)++;
13662  }
13663  continue;
13664  }
13665 
13666  /* check, if we want to aggregate an (in)equality with an equality:
13667  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13668  */
13669  if( tryaggregation )
13670  {
13671  SCIP_Bool aggregated;
13672 
13673  assert(consdata0->nvars == nvarscommon + nvars0minus1);
13674  assert(consdata1->nvars == nvarscommon + nvars1minus0);
13675 
13676  aggregated = FALSE;
13677  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13678  {
13679  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13680  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13681  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13682  nchgcoefs, &aggregated) );
13683 
13684  /* update array of active constraints */
13685  if( aggregated )
13686  {
13687  assert(!SCIPconsIsActive(cons0));
13688  assert(SCIPconsIsActive(cons1));
13689  conss[chkind] = NULL;
13690  }
13691  }
13692  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13693  {
13694  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13695  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13696  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13697  nchgcoefs, &aggregated) );
13698 
13699  /* update array of active constraints */
13700  if( aggregated )
13701  {
13702  assert(!SCIPconsIsActive(cons1));
13703  assert(SCIPconsIsActive(cons0));
13704  conss[c] = NULL;
13705  }
13706  }
13707  }
13708  }
13709 
13710  /* free temporary memory */
13711  SCIPfreeBufferArray(scip, &diffidx1minus0);
13712  SCIPfreeBufferArray(scip, &diffidx0minus1);
13713  SCIPfreeBufferArray(scip, &commonidx1);
13714  SCIPfreeBufferArray(scip, &commonidx0);
13715 
13716  return SCIP_OKAY;
13717 }
13718 
13719 /** do stuffing presolving on a single constraint */
13720 static
13722  SCIP* scip, /**< SCIP data structure */
13723  SCIP_CONS* cons, /**< linear constraint */
13724  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13725  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13726  * constraints using the cheapest variable? */
13727  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13728  int* nfixedvars, /**< pointer to count the total number of fixed variables */
13729  int* nchgbds /**< pointer to count the total number of tightened bounds */
13730  )
13731 {
13732  SCIP_CONSDATA* consdata;
13733  SCIP_Real* ratios;
13734  int* varpos;
13735  SCIP_Bool* swapped;
13736  SCIP_VAR** vars;
13737  SCIP_Real* vals;
13738  SCIP_VAR* var;
13739  SCIP_Real lb;
13740  SCIP_Real ub;
13741  SCIP_Real minactivity;
13742  SCIP_Real maxactivity;
13743  SCIP_Real maxcondactivity;
13744  SCIP_Real mincondactivity;
13745  SCIP_Real rhs;
13746  SCIP_Real val;
13747  SCIP_Real obj;
13748  SCIP_Real factor;
13749  SCIP_Bool minactisrelax;
13750  SCIP_Bool maxactisrelax;
13751  SCIP_Bool tryfixing;
13752  int nsingletons;
13753  int idx;
13754  int v;
13755  int nvars;
13756 
13757  assert(scip != NULL);
13758  assert(cons != NULL);
13759  assert(nfixedvars != NULL);
13760 
13761  consdata = SCIPconsGetData(cons);
13762 
13763  /* we only want to run for inequalities */
13764  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13765  return SCIP_OKAY;
13766 
13767  if( singlevarstuffing )
13768  {
13769  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13770  }
13771  else
13772  {
13773  minactivity = SCIP_INVALID;
13774  maxactivity = SCIP_INVALID;
13775  }
13776 
13777  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13778  * the new maxactivity is minus the old minactivity then
13779  */
13780  if( SCIPisInfinity(scip, consdata->rhs) )
13781  {
13782  SCIP_Real tmp;
13783  rhs = -consdata->lhs;
13784  factor = -1.0;
13785  tmp = maxactivity;
13786  maxactivity = -minactivity;
13787  minactivity = -tmp;
13788  }
13789  else
13790  {
13791  assert(SCIPisInfinity(scip, -consdata->lhs));
13792  rhs = consdata->rhs;
13793  factor = 1.0;
13794  }
13795 
13796  nvars = consdata->nvars;
13797  vars = consdata->vars;
13798  vals = consdata->vals;
13799 
13800  /* check for continuous singletons */
13801  if( singletonstuffing )
13802  {
13803  for( v = 0; v < nvars; ++v )
13804  {
13805  var = vars[v];
13806 
13807  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13809  break;
13810  }
13811  }
13812  else
13813  /* we don't want to go into the next block */
13814  v = nvars;
13815 
13816  /* a singleton was found -> perform singleton variable stuffing */
13817  if( v < nvars )
13818  {
13819  assert(singletonstuffing);
13820 
13821  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
13822  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
13823  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
13824 
13825  tryfixing = TRUE;
13826  nsingletons = 0;
13827  mincondactivity = 0.0;
13828  maxcondactivity = 0.0;
13829 
13830  for( v = 0; v < nvars; ++v )
13831  {
13832  var = vars[v];
13833  lb = SCIPvarGetLbGlobal(var);
13834  ub = SCIPvarGetUbGlobal(var);
13835  obj = SCIPvarGetObj(var);
13836  val = factor * vals[v];
13837 
13838  assert(!SCIPisZero(scip, val));
13839 
13840  /* the variable is a singleton and continuous */
13841  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13843  {
13844  if( SCIPisNegative(scip, obj) && val > 0 )
13845  {
13846  /* case 1: obj < 0 and coef > 0 */
13847  if( SCIPisInfinity(scip, -lb) )
13848  {
13849  tryfixing = FALSE;
13850  break;
13851  }
13852 
13853  maxcondactivity += val * lb;
13854  mincondactivity += val * lb;
13855  swapped[v] = FALSE;
13856  ratios[nsingletons] = obj / val;
13857  varpos[nsingletons] = v;
13858  nsingletons++;
13859  }
13860  else if( SCIPisPositive(scip, obj) && val < 0 )
13861  {
13862  /* case 2: obj > 0 and coef < 0 */
13863  if( SCIPisInfinity(scip, ub) )
13864  {
13865  tryfixing = FALSE;
13866  break;
13867  }
13868  /* multiply column by (-1) to become case 1.
13869  * now bounds are swapped: ub := -lb, lb := -ub
13870  */
13871 
13872  maxcondactivity += val * ub;
13873  mincondactivity += val * ub;
13874  swapped[v] = TRUE;
13875  ratios[nsingletons] = obj / val;
13876  varpos[nsingletons] = v;
13877  nsingletons++;
13878  }
13879  else if( val > 0 )
13880  {
13881  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
13882  * we only consider the lower bound for the constants
13883  */
13884  assert(!SCIPisNegative(scip, obj));
13885 
13886  if( SCIPisInfinity(scip, -lb) )
13887  {
13888  /* maybe unbounded */
13889  tryfixing = FALSE;
13890  break;
13891  }
13892 
13893  maxcondactivity += val * lb;
13894  mincondactivity += val * lb;
13895  }
13896  else
13897  {
13898  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
13899  * we only consider the upper bound for the constants
13900  */
13901  assert(!SCIPisPositive(scip, obj));
13902  assert(val < 0);
13903 
13904  if( SCIPisInfinity(scip, ub) )
13905  {
13906  /* maybe unbounded */
13907  tryfixing = FALSE;
13908  break;
13909  }
13910 
13911  maxcondactivity += val * ub;
13912  mincondactivity += val * ub;
13913  }
13914  }
13915  else
13916  {
13917  /* consider contribution of discrete variables, non-singleton
13918  * continuous variables and variables with more than one lock
13919  */
13920  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13921  {
13922  tryfixing = FALSE;
13923  break;
13924  }
13925 
13926  if( val > 0 )
13927  {
13928  maxcondactivity += val * ub;
13929  mincondactivity += val * lb;
13930  }
13931  else
13932  {
13933  maxcondactivity += val * lb;
13934  mincondactivity += val * ub;
13935  }
13936  }
13937  }
13938  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
13939  {
13940  SCIP_Real delta;
13941  SCIP_Bool tightened;
13942 #ifdef SCIP_DEBUG
13943  int oldnfixedvars = *nfixedvars;
13944  int oldnchgbds = *nchgbds;
13945 #endif
13946 
13947  SCIPsortRealInt(ratios, varpos, nsingletons);
13948 
13949  /* verify which singleton continuous variables can be fixed */
13950  for( v = 0; v < nsingletons; ++v )
13951  {
13952  idx = varpos[v];
13953  var = vars[idx];
13954  val = factor * vals[idx];
13955  lb = SCIPvarGetLbGlobal(var);
13956  ub = SCIPvarGetUbGlobal(var);
13957 
13958  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
13959  assert((val < 0) == swapped[idx]);
13960  val = REALABS(val);
13961 
13962  /* stop fixing if variable bounds are not finite */
13963  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13964  break;
13965 
13966  assert((SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1);
13967  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
13968 
13969  /* calculate the change in the row activities if this variable changes
13970  * its value from its worst to its best bound
13971  */
13972  if( swapped[idx] )
13973  delta = -(lb - ub) * val;
13974  else
13975  delta = (ub - lb) * val;
13976 
13977  assert(!SCIPisNegative(scip, delta));
13978 
13979  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
13980  {
13981  if( swapped[idx] )
13982  {
13983  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
13984  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
13985 
13986  }
13987  else
13988  {
13989  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
13990  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
13991  }
13992 
13993  if( *cutoff )
13994  break;
13995  if( tightened )
13996  {
13997  (*nfixedvars)++;
13998  }
13999  }
14000  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14001  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14002  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14003  * troubles in case of large bounds.
14004  */
14005  else if( SCIPisLE(scip, rhs, mincondactivity) )
14006  {
14007  if( swapped[idx] )
14008  {
14009  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14010  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14011  }
14012  else
14013  {
14014  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14015  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14016  }
14017 
14018  if( *cutoff )
14019  break;
14020  if( tightened )
14021  {
14022  (*nfixedvars)++;
14023  }
14024  }
14025 
14026  maxcondactivity += delta;
14027  mincondactivity += delta;
14028  }
14029 
14030 #ifdef SCIP_DEBUG
14031  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14032  {
14033  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14034  }
14035 #endif
14036  }
14037 
14038  SCIPfreeBufferArray(scip, &swapped);
14039  SCIPfreeBufferArray(scip, &ratios);
14040  SCIPfreeBufferArray(scip, &varpos);
14041  }
14042 
14043  /* perform single-variable stuffing:
14044  * for a linear inequality
14045  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14046  * with a_i > 0 and objective coefficients c_i < 0,
14047  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14048  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14049  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14050  * is redundant.
14051  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14052  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14053  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14054  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14055  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14056  * upper bound.
14057  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14058  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14059  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14060  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14061  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14062  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14063  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14064  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14065  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14066  * c_k * ceil((maxactivity - rhs)/val) is still better than
14067  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14068  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14069  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14070  * sign of coefficients in constraint and objective prevent the use of this method.
14071  */
14072  if( singlevarstuffing && !SCIPisInfinity(scip, -minactivity) )
14073  {
14074  SCIP_Real bestratio = -SCIPinfinity(scip);
14075  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14076  SCIP_Real ratio;
14077  int bestindex = -1;
14078  int bestuplocks = 0;
14079  int bestdownlocks = 1;
14080  int downlocks;
14081  int uplocks;
14082  int oldnfixedvars;
14083  int oldnchgbds;
14084 
14085  SCIPdebug( oldnfixedvars = *nfixedvars; )
14086  SCIPdebug( oldnchgbds = *nchgbds; )
14087  /* loop over all variables to identify the best and second-best ratio */
14088  for( v = 0; v < nvars; ++v )
14089  {
14090  var = vars[v];
14091  obj = SCIPvarGetObj(var);
14092  val = factor * vals[v];
14093 
14094  assert(!SCIPisZero(scip, val));
14095 
14096  ratio = obj / val;
14097 
14098  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14099  if( !SCIPisNegative(scip, ratio) )
14100  {
14101  bestindex = -1;
14102  break;
14103  }
14104 
14105  if( val > 0 )
14106  {
14107  downlocks = SCIPvarGetNLocksDown(var);
14108  uplocks = SCIPvarGetNLocksUp(var);
14109  }
14110  else
14111  {
14112  downlocks = SCIPvarGetNLocksUp(var);
14113  uplocks = SCIPvarGetNLocksDown(var);
14114  }
14115 
14116  /* better ratio, update best candidate
14117  * @todo use some tolerance
14118  * @todo check size of domain and updated ratio for integer variables already?
14119  */
14120  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14121  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14122  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14123  {
14124  /* best index becomes second-best*/
14125  if( bestindex != -1 )
14126  {
14127  /* second-best index must not have more than 1 uplock */
14128  if( bestuplocks > 1 )
14129  {
14130  bestindex = -1;
14131  break;
14132  }
14133  else
14134  {
14135  secondbestratio = bestratio;
14136  }
14137  }
14138  bestdownlocks = downlocks;
14139  bestuplocks = uplocks;
14140  bestratio = ratio;
14141  bestindex = v;
14142 
14143  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14144  * if it is not the best, it has too many uplocks -> not applicable
14145  */
14146  if( bestdownlocks > 0 && bestuplocks > 1 )
14147  {
14148  bestindex = -1;
14149  break;
14150  }
14151  }
14152  else
14153  {
14154  /* non-best index must not have more than 1 uplock */
14155  if( uplocks > 1 )
14156  {
14157  bestindex = -1;
14158  break;
14159  }
14160  /* update second-best ratio */
14161  if( ratio > secondbestratio )
14162  {
14163  secondbestratio = ratio;
14164  }
14165  }
14166  }
14167 
14168  /* check if we can apply single variable stuffing */
14169  if( bestindex != -1 && bestdownlocks == 0 )
14170  {
14171  SCIP_Bool tightened = FALSE;
14172  SCIP_Real bounddelta;
14173 
14174  var = vars[bestindex];
14175  obj = SCIPvarGetObj(var);
14176  val = factor * vals[bestindex];
14177  lb = SCIPvarGetLbGlobal(var);
14178  ub = SCIPvarGetUbGlobal(var);
14179  tryfixing = TRUE;
14180 
14181  if( val < 0 )
14182  {
14183  assert(!SCIPisNegative(scip, obj));
14184 
14185  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14186  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14187  {
14188  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14189  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14190  assert(SCIPisPositive(scip, activitydelta));
14191 
14192  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14193 
14194  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14195  assert(SCIPisPositive(scip, bounddelta));
14196  }
14197  else
14198  bounddelta = (maxactivity - rhs)/-val;
14199 
14200  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14201 
14202  if( tryfixing )
14203  {
14204  assert(SCIPvarGetNLocksUp(var) == 0);
14205 
14206  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14207  {
14208  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14209  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14210  }
14211  else
14212  {
14213  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14214  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14215  }
14216  }
14217  }
14218  else
14219  {
14220  assert(!SCIPisPositive(scip, obj));
14221 
14222  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14223  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14224  {
14225  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14226  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14227  assert(SCIPisPositive(scip, activitydelta));
14228 
14229  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14230 
14231  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14232  assert(SCIPisPositive(scip, bounddelta));
14233  }
14234  else
14235  bounddelta = (maxactivity - rhs)/val;
14236 
14237  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14238 
14239  if( tryfixing )
14240  {
14241  assert(SCIPvarGetNLocksDown(var) == 0);
14242 
14243  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14244  {
14245  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14246  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14247  }
14248  else
14249  {
14250  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14251  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14252  }
14253  }
14254  }
14255 
14256  if( *cutoff )
14257  return SCIP_OKAY;
14258  if( tightened )
14259  {
14260  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14261  ++(*nfixedvars);
14262  else
14263  ++(*nchgbds);
14264 
14265  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14266  for( v = 0; v < nvars; ++v )
14267  {
14268  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]),
14269  SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]), SCIPvarGetNLocksDown(vars[v]), SCIPvarGetNLocksUp(vars[v]),
14270  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14271  }
14272  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14273 
14274  for( v = 0; v < nvars; ++v )
14275  {
14276  if( v == bestindex )
14277  continue;
14278 
14279  if( factor * vals[v] < 0 )
14280  {
14281  assert(SCIPvarGetNLocksDown(vars[v]) == 1);
14282  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14283  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14284  }
14285  else
14286  {
14287  assert(SCIPvarGetNLocksUp(vars[v]) == 1);
14288  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14289  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14290  }
14291 
14292  if( *cutoff )
14293  return SCIP_OKAY;
14294  if( tightened )
14295  ++(*nfixedvars);
14296  }
14297  SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14298  }
14299  }
14300  }
14301 
14302  return SCIP_OKAY;
14303 }
14304 
14305 /** applies full dual presolving on variables that only appear in linear constraints */
14306 static
14308  SCIP* scip, /**< SCIP data structure */
14309  SCIP_CONS** conss, /**< constraint set */
14310  int nconss, /**< number of constraints */
14311  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14312  int* nchgbds /**< pointer to count the number of bound changes */
14313  )
14314 {
14315  SCIP_Real* redlb;
14316  SCIP_Real* redub;
14317  int* nlocksdown;
14318  int* nlocksup;
14319  SCIP_Bool* isimplint;
14320  SCIP_VAR** origvars;
14321  SCIP_VAR** vars;
14322  SCIP_VAR** conscontvars;
14323  int nvars;
14324  int nbinvars;
14325  int nintvars;
14326  int ncontvars;
14327  int v;
14328  int c;
14329 
14330  /* we calculate redundancy bounds with the following meaning:
14331  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14332  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14333  * then:
14334  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14335  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14336  */
14337 
14338  /* Additionally, we detect continuous variables that are implicitly integral.
14339  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14340  * and all constraints (including the bounds as trivial constraints) in which:
14341  * c_j > 0: the variable is down-locked,
14342  * c_j < 0: the variable is up-locked,
14343  * c_j = 0: the variable appears
14344  * have, apart from j, only integer variables with integral coefficients and integral sides.
14345  * This is because then, the value of the variable is either determined by one of its bounds or
14346  * by one of these constraints, and in all cases, the value of the variable is integral.
14347  */
14348 
14349  assert(scip != NULL);
14350  assert(nconss == 0 || conss != NULL);
14351  assert(nchgbds != NULL);
14352  assert(!SCIPinProbing(scip));
14353 
14354  /* get active variables */
14355  nvars = SCIPgetNVars(scip);
14356  origvars = SCIPgetVars(scip);
14357 
14358  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14359  nbinvars = SCIPgetNBinVars(scip);
14360  if( nbinvars == nvars )
14361  return SCIP_OKAY;
14362 
14363  /* get number of continuous variables */
14364  ncontvars = SCIPgetNContVars(scip);
14365  nintvars = nvars - ncontvars;
14366 
14367  /* copy the variable array since this array might change during the curse of this algorithm */
14368  nvars = nvars - nbinvars;
14369  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14370 
14371  /* allocate temporary memory */
14372  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14373  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14374  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14375  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14376  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14377  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14378 
14379  /* initialize redundancy bounds */
14380  for( v = 0; v < nvars; ++v )
14381  {
14382  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14383  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14384  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14385  }
14386  BMSclearMemoryArray(nlocksdown, nvars);
14387  BMSclearMemoryArray(nlocksup, nvars);
14388 
14389  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14390  * We better not use SCIPisFeasIntegral() in these checks.
14391  */
14392  for( v = 0; v < ncontvars; v++ )
14393  {
14394  SCIP_VAR* var;
14395  SCIP_Real obj;
14396  SCIP_Real lb;
14397  SCIP_Real ub;
14398 
14399  var = vars[v + nintvars - nbinvars];
14400  lb = SCIPvarGetLbGlobal(var);
14401  ub = SCIPvarGetUbGlobal(var);
14402 
14403  obj = SCIPvarGetObj(var);
14404  if( SCIPisZero(scip, obj) )
14405  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14406  else
14407  {
14408  if( SCIPisPositive(scip, obj) )
14409  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14410  else
14411  {
14412  assert(SCIPisNegative(scip, obj));
14413  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14414  }
14415  }
14416  }
14417 
14418  /* scan all constraints */
14419  for( c = 0; c < nconss; ++c )
14420  {
14421  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14422  * part of checked disjunctions)
14423  */
14424  if( SCIPconsIsLocked(conss[c]) )
14425  {
14426  SCIP_CONSDATA* consdata;
14427  SCIP_Bool lhsexists;
14428  SCIP_Bool rhsexists;
14429  SCIP_Bool hasimpliedpotential;
14430  SCIP_Bool integralcoefs;
14431  int nlockspos;
14432  int contvarpos;
14433  int nconscontvars;
14434  int i;
14435 
14436  consdata = SCIPconsGetData(conss[c]);
14437  assert(consdata != NULL);
14438 
14439  /* get number of times the constraint was locked */
14440  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14441 
14442  /* we do not want to include constraints with locked negation (this would be too weird) */
14443  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14444  {
14445  /* mark all continuous variables as not being implicit integral */
14446  for( i = 0; i < consdata->nvars; ++i )
14447  {
14448  SCIP_VAR* var;
14449 
14450  var = consdata->vars[i];
14452  {
14453  int contv;
14454  contv = SCIPvarGetProbindex(var) - nintvars;
14455  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14456  isimplint[contv] = FALSE;
14457  }
14458  }
14459  continue;
14460  }
14461 
14462  /* check for existing sides */
14463  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14464  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14465 
14466  /* count locks and update redundancy bounds */
14467  contvarpos = -1;
14468  nconscontvars = 0;
14469  hasimpliedpotential = FALSE;
14470  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14471 
14472  for( i = 0; i < consdata->nvars; ++i )
14473  {
14474  SCIP_VAR* var;
14475  SCIP_Real val;
14476  SCIP_Real minresactivity;
14477  SCIP_Real maxresactivity;
14478  SCIP_Real newredlb;
14479  SCIP_Real newredub;
14480  SCIP_Bool minisrelax;
14481  SCIP_Bool maxisrelax;
14482  SCIP_Bool isminsettoinfinity;
14483  SCIP_Bool ismaxsettoinfinity;
14484  int arrayindex;
14485 
14486  var = consdata->vars[i];
14487  val = consdata->vals[i];
14488 
14489  /* check if still all integer variables have integral coefficients */
14490  if( SCIPvarIsIntegral(var) )
14491  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14492 
14493  /* we do not need to process binary variables */
14494  if( SCIPvarIsBinary(var) )
14495  continue;
14496 
14497  if( SCIPconsIsModifiable(conss[c]) )
14498  {
14499  minresactivity = -SCIPinfinity(scip);
14500  maxresactivity = SCIPinfinity(scip);
14501  isminsettoinfinity = TRUE;
14502  ismaxsettoinfinity = TRUE;
14503  }
14504  else
14505  {
14506  /* calculate residual activity bounds if variable would be fixed to zero */
14507  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14508  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14509 
14510  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14511  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14512  * This is needed, because we do not want to rely on relaxed finite resactivities.
14513  */
14514  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14515 
14516  /* check minresactivity for reliability */
14517  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14518  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14519 
14520  /* check maxresactivity for reliability */
14521  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14522  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14523  }
14524 
14525  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14526 
14527  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14528 
14529  newredlb = redlb[arrayindex];
14530  newredub = redub[arrayindex];
14531  if( val > 0.0 )
14532  {
14533  if( lhsexists )
14534  {
14535  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14536  nlocksdown[arrayindex] += nlockspos;
14537  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14538  }
14539  if( rhsexists )
14540  {
14541  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14542  nlocksup[arrayindex] += nlockspos;
14543  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14544  }
14545  }
14546  else
14547  {
14548  if( lhsexists )
14549  {
14550  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14551  nlocksup[arrayindex] += nlockspos;
14552  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14553  }
14554  if( rhsexists )
14555  {
14556  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14557  nlocksdown[arrayindex] += nlockspos;
14558  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14559  }
14560  }
14561 
14562  /* if the variable is integer, we have to round the value to the next integral value */
14563  if( SCIPvarIsIntegral(var) )
14564  {
14565  if( !SCIPisInfinity(scip, newredlb) )
14566  newredlb = SCIPceil(scip, newredlb);
14567  if( !SCIPisInfinity(scip, -newredub) )
14568  newredub = SCIPfloor(scip, newredub);
14569  }
14570 
14571  /* update redundancy bounds */
14572  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14573  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14574 
14575  /* collect the continuous variables of the constraint */
14577  {
14578  int contv;
14579 
14580  assert(nconscontvars < ncontvars);
14581  contvarpos = i;
14582  conscontvars[nconscontvars] = var;
14583  nconscontvars++;
14584 
14585  contv = SCIPvarGetProbindex(var) - nintvars;
14586  assert(0 <= contv && contv < ncontvars);
14587  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14588  }
14589  }
14590 
14591  /* update implied integer status of continuous variables */
14592  if( hasimpliedpotential )
14593  {
14594  if( nconscontvars > 1 || !integralcoefs )
14595  {
14596  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14597  * none of the continuous variables is implied integer
14598  */
14599  for( i = 0; i < nconscontvars; i++ )
14600  {
14601  int contv;
14602  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14603  assert(0 <= contv && contv < ncontvars);
14604  isimplint[contv] = FALSE;
14605  }
14606  }
14607  else
14608  {
14609  SCIP_VAR* var;
14610  SCIP_Real val;
14611  SCIP_Real absval;
14612  int contv;
14613 
14614  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14615  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14616  * side(s) of the constraint is integral
14617  */
14618  assert(nconscontvars == 1);
14619  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14620  var = consdata->vars[contvarpos];
14621  val = consdata->vals[contvarpos];
14622  contv = SCIPvarGetProbindex(var) - nintvars;
14623  assert(0 <= contv && contv < ncontvars);
14624  assert(isimplint[contv]);
14625 
14626  absval = REALABS(val);
14627  if( !SCIPisEQ(scip, absval, 1.0) )
14628  isimplint[contv] = FALSE;
14629  else
14630  {
14631  SCIP_Real obj;
14632 
14633  obj = SCIPvarGetObj(var);
14634  if( obj * val >= 0.0 && lhsexists )
14635  {
14636  /* the variable may be blocked by the constraint's left hand side */
14637  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14638  }
14639  if( obj * val <= 0.0 && rhsexists )
14640  {
14641  /* the variable may be blocked by the constraint's left hand side */
14642  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14643  }
14644  }
14645  }
14646  }
14647  }
14648  }
14649 
14650  /* check if any bounds can be tightened due to optimality */
14651  for( v = 0; v < nvars; ++v )
14652  {
14653  SCIP_VAR* var;
14654  SCIP_Real obj;
14655  SCIP_Bool infeasible;
14656  SCIP_Bool tightened;
14657 
14658  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14659  assert(SCIPvarGetNLocksDown(vars[v]) >= nlocksdown[v]);
14660  assert(SCIPvarGetNLocksUp(vars[v]) >= nlocksup[v]);
14661 
14662  var = vars[v];
14663  obj = SCIPvarGetObj(var);
14664  if( obj >= 0.0 )
14665  {
14666  /* making the variable as small as possible does not increase the objective:
14667  * check if all down locks of the variables are due to linear constraints;
14668  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14669  */
14670  if( SCIPvarGetNLocksDown(var) == nlocksdown[v]
14671  && !SCIPisInfinity(scip, -redlb[v])
14672  && redlb[v] < SCIPvarGetUbGlobal(var) )
14673  {
14674  SCIP_Real ub;
14675 
14676  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14677  * -> tighten upper bound to x_v <= redlb[v]
14678  */
14679  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14681  redlb[v]);
14682  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14683  assert(!infeasible);
14684 
14685  ub = SCIPvarGetUbGlobal(var);
14686  redub[v] = MIN(redub[v], ub);
14687  if( tightened )
14688  (*nchgbds)++;
14689  }
14690  }
14691  if( obj <= 0.0 )
14692  {
14693  /* making the variable as large as possible does not increase the objective:
14694  * check if all up locks of the variables are due to linear constraints;
14695  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14696  */
14697  if( SCIPvarGetNLocksUp(var) == nlocksup[v]
14698  && !SCIPisInfinity(scip, redub[v])
14699  && redub[v] > SCIPvarGetLbGlobal(var) )
14700  {
14701  SCIP_Real lb;
14702 
14703  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14704  * -> tighten lower bound to x_v >= redub[v]
14705  */
14706  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14708  redub[v]);
14709  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14710  assert(!infeasible);
14711 
14712  lb = SCIPvarGetLbGlobal(var);
14713  redlb[v] = MAX(redlb[v], lb);
14714  if( tightened )
14715  (*nchgbds)++;
14716  }
14717  }
14718  }
14719 
14720  /* upgrade continuous variables to implied integers */
14721  for( v = nintvars - nbinvars; v < nvars; ++v )
14722  {
14723  SCIP_VAR* var;
14724  SCIP_Bool infeasible;
14725 
14726  var = vars[v];
14727  assert(var != NULL);
14728 
14729  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14730  assert(SCIPvarGetNLocksDown(var) >= nlocksdown[v]);
14731  assert(SCIPvarGetNLocksUp(var) >= nlocksup[v]);
14732  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14733 
14734  /* we can only conclude implied integrality if the variable appears in no other constraint */
14735  if( isimplint[v - nintvars + nbinvars]
14736  && SCIPvarGetNLocksDown(var) == nlocksdown[v]
14737  && SCIPvarGetNLocksUp(var) == nlocksup[v] )
14738  {
14739 
14740  /* since we locally copied the variable array we can change the variable type immediately */
14741  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
14742 
14743  if( infeasible )
14744  {
14745  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14746  *cutoff = TRUE;
14747 
14748  break;
14749  }
14750 
14751  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
14753  }
14754  }
14755 
14756  /* free temporary memory */
14757  SCIPfreeBufferArray(scip, &conscontvars);
14758  SCIPfreeBufferArray(scip, &isimplint);
14759  SCIPfreeBufferArray(scip, &nlocksup);
14760  SCIPfreeBufferArray(scip, &nlocksdown);
14761  SCIPfreeBufferArray(scip, &redub);
14762  SCIPfreeBufferArray(scip, &redlb);
14763 
14764  SCIPfreeBufferArray(scip, &vars);
14765 
14766  return SCIP_OKAY;
14767 }
14768 
14769 /** helper function to enforce constraints */
14770 static
14772  SCIP* scip, /**< SCIP data structure */
14773  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14774  SCIP_CONS** conss, /**< constraints to process */
14775  int nconss, /**< number of constraints */
14776  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14777  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14778  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14779  )
14780 {
14781  SCIP_CONSHDLRDATA* conshdlrdata;
14782  SCIP_Bool checkrelmaxabs;
14783  SCIP_Bool violated;
14784  SCIP_Bool cutoff = FALSE;
14785  int c;
14786 
14787  assert(scip != NULL);
14788  assert(conshdlr != NULL);
14789  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14790  assert(result != NULL);
14791 
14792  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14793  assert(conshdlrdata != NULL);
14794 
14795  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14796 
14797  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14798 
14799  /* check for violated constraints
14800  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14801  */
14802  *result = SCIP_FEASIBLE;
14803 
14804  /* check all useful linear constraints for feasibility */
14805  for( c = 0; c < nusefulconss; ++c )
14806  {
14807  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14808 
14809  if( violated )
14810  {
14811  /* insert LP row as cut */
14812  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14813  if ( cutoff )
14814  *result = SCIP_CUTOFF;
14815  else
14816  *result = SCIP_SEPARATED;
14817  }
14818  }
14819 
14820  /* check all obsolete linear constraints for feasibility */
14821  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14822  {
14823  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14824 
14825  if( violated )
14826  {
14827  /* insert LP row as cut */
14828  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14829  if ( cutoff )
14830  *result = SCIP_CUTOFF;
14831  else
14832  *result = SCIP_SEPARATED;
14833  }
14834  }
14835 
14836  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
14837 
14838  return SCIP_OKAY;
14839 }
14840 
14841 /*
14842  * Callback methods of constraint handler
14843  */
14844 
14845 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
14846 static
14847 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
14848 { /*lint --e{715}*/
14849  assert(scip != NULL);
14850  assert(conshdlr != NULL);
14851  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14852 
14853  /* call inclusion method of constraint handler */
14855 
14856  *valid = TRUE;
14857 
14858  return SCIP_OKAY;
14859 }
14860 
14861 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
14862 static
14863 SCIP_DECL_CONSFREE(consFreeLinear)
14864 { /*lint --e{715}*/
14865  SCIP_CONSHDLRDATA* conshdlrdata;
14866 
14867  assert(scip != NULL);
14868  assert(conshdlr != NULL);
14869  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14870 
14871  /* free constraint handler data */
14872  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14873  assert(conshdlrdata != NULL);
14874 
14875  conshdlrdataFree(scip, &conshdlrdata);
14876 
14877  SCIPconshdlrSetData(conshdlr, NULL);
14878 
14879  return SCIP_OKAY;
14881 
14882 
14883 /** initialization method of constraint handler (called after problem was transformed) */
14884 static
14885 SCIP_DECL_CONSINIT(consInitLinear)
14886 {
14887  SCIP_CONSHDLRDATA* conshdlrdata;
14888  int c;
14889 
14890  assert(scip != NULL);
14891 
14892  /* check for event handler */
14893  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14894  assert(conshdlrdata != NULL);
14895  assert(conshdlrdata->eventhdlr != NULL);
14896  assert(nconss == 0 || conss != NULL);
14897 
14898  /* catch events for the constraints */
14899  for( c = 0; c < nconss; ++c )
14900  {
14901  /* catch all events */
14902  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14903  }
14904 
14905  return SCIP_OKAY;
14906 }
14907 
14908 
14909 /** deinitialization method of constraint handler (called before transformed problem is freed) */
14910 static
14911 SCIP_DECL_CONSEXIT(consExitLinear)
14912 {
14913  SCIP_CONSHDLRDATA* conshdlrdata;
14914  int c;
14915 
14916  assert(scip != NULL);
14917 
14918  /* check for event handler */
14919  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14920  assert(conshdlrdata != NULL);
14921  assert(conshdlrdata->eventhdlr != NULL);
14922 
14923  /* drop events for the constraints */
14924  for( c = nconss - 1; c >= 0; --c )
14925  {
14926  SCIP_CONSDATA* consdata;
14927 
14928  consdata = SCIPconsGetData(conss[c]);
14929  assert(consdata != NULL);
14930 
14931  if( consdata->eventdata != NULL )
14932  {
14933  /* drop all events */
14934  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14935  assert(consdata->eventdata == NULL);
14936  }
14937  }
14938 
14939  return SCIP_OKAY;
14940 
14941 }
14942 
14943 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14944 static
14946  SCIP* scip, /**< SCIP data structure */
14947  SCIP_Real lhs, /**< left hand side */
14948  SCIP_Real rhs /**< right hand side */
14949  )
14950 {
14951  assert(scip != NULL);
14952 
14953  return !(SCIPisEQ(scip, lhs, rhs)
14954  || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
14955 }
14956 
14957 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14958 static
14960  SCIP* scip, /**< SCIP data structure */
14961  SCIP_Real x /**< value */
14962  )
14963 {
14964  assert(scip != NULL);
14965 
14966  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
14967 }
14968 
14969 /** performs linear constraint type classification as used for MIPLIB
14970  *
14971  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
14972  *
14973  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
14974  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
14975  * Similarly, if specialized constraints were created through the API, these are currently not present.
14976  */
14978  SCIP* scip, /**< SCIP data structure */
14979  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
14980  )
14981 {
14982  int c;
14983  SCIP_CONSHDLR* conshdlr;
14984  SCIP_CONS** conss;
14985  int nconss;
14986 
14987  assert(scip != NULL);
14988  assert(linconsstats != NULL);
14989  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14990  assert(conshdlr != NULL);
14991 
14992  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
14993  {
14994  conss = SCIPgetConss(scip);
14995  nconss = SCIPgetNConss(scip);
14996  }
14997  else
14998  {
14999  conss = SCIPconshdlrGetConss(conshdlr);
15000  nconss = SCIPconshdlrGetNConss(conshdlr);
15001  }
15002 
15003 
15004  /* reset linear constraint type classification */
15005  SCIPlinConsStatsReset(linconsstats);
15006 
15007  /* loop through all constraints */
15008  for( c = 0; c < nconss; c++ )
15009  {
15010  SCIP_CONS* cons;
15011  SCIP_CONSDATA* consdata;
15012  SCIP_Real lhs;
15013  SCIP_Real rhs;
15014  int i;
15015 
15016  /* get constraint */
15017  cons = conss[c];
15018  assert(cons != NULL);
15019 
15020  /* skip constraints that are not handled by the constraint handler */
15021  if( SCIPconsGetHdlr(cons) != conshdlr )
15022  continue;
15023 
15024  /* get constraint data */
15025  consdata = SCIPconsGetData(cons);
15026  assert(consdata != NULL);
15027  rhs = consdata->rhs;
15028  lhs = consdata->lhs;
15029 
15030  /* merge multiples and delete variables with zero coefficient */
15031  SCIP_CALL( mergeMultiples(scip, cons) );
15032  for( i = 0; i < consdata->nvars; i++ )
15033  {
15034  assert(!SCIPisZero(scip, consdata->vals[i]));
15035  }
15036 
15037  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15038  if( consdata->nvars == 0 )
15039  {
15040  SCIPdebugMsg(scip, "classified as EMPTY: ");
15041  SCIPdebugPrintCons(scip, cons, NULL);
15043 
15044  continue;
15045  }
15046 
15047  /* is constraint of type SCIP_CONSTYPE_FREE? */
15048  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15049  {
15050  SCIPdebugMsg(scip, "classified as FREE: ");
15051  SCIPdebugPrintCons(scip, cons, NULL);
15053 
15054  continue;
15055  }
15056 
15057  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15058  if( consdata->nvars == 1 )
15059  {
15060  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15061  SCIPdebugPrintCons(scip, cons, NULL);
15062  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15063 
15064  continue;
15065  }
15066 
15067  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15068  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15069  {
15070  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15071  SCIPdebugPrintCons(scip, cons, NULL);
15073 
15074  continue;
15075  }
15076 
15077  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15078  if( consdata->nvars == 2 )
15079  {
15080  SCIP_LINCONSTYPE constype;
15081 
15082  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15083  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15084  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15085  {
15086  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15087  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15088  }
15089  else
15090  {
15091  constype = SCIP_LINCONSTYPE_VARBOUND;
15092  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15093  }
15094  SCIPdebugPrintCons(scip, cons, NULL);
15095 
15096  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15097 
15098  continue;
15099  }
15100 
15101  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15102  {
15103  SCIP_Real scale;
15104  SCIP_Real b;
15105  SCIP_Bool unmatched;
15106  int nnegbinvars;
15107 
15108  unmatched = FALSE;
15109  nnegbinvars = 0;
15110 
15111  scale = REALABS(consdata->vals[0]);
15112 
15113  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15114  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15115  {
15116  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15117  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15118  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15119  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15120 
15121  if( consdata->vals[i] < 0.0 )
15122  nnegbinvars++;
15123  }
15124 
15125  if( !unmatched )
15126  {
15127  if( SCIPisEQ(scip, lhs, rhs) )
15128  {
15129  b = rhs/scale + nnegbinvars;
15130  if( SCIPisEQ(scip, 1.0, b) )
15131  {
15132  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15133  SCIPdebugPrintCons(scip, cons, NULL);
15135 
15136  continue;
15137  }
15138  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15139  {
15140  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15141  SCIPdebugPrintCons(scip, cons, NULL);
15143 
15144  continue;
15145  }
15146  }
15147 
15148  /* compute right hand side divided by scale */
15149  if( !SCIPisInfinity(scip, rhs) )
15150  b = rhs/scale + nnegbinvars;
15151  else
15152  b = SCIPinfinity(scip);
15153 
15154  if( SCIPisEQ(scip, 1.0, b) )
15155  {
15156  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15157  SCIPdebugPrintCons(scip, cons, NULL);
15159 
15160  /* relax right hand side to prevent further classifications */
15161  rhs = SCIPinfinity(scip);
15162  }
15163  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15164  {
15165  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15166  SCIPdebugPrintCons(scip, cons, NULL);
15167 
15169 
15170  /* relax right hand side to prevent further classifications */
15171  rhs = SCIPinfinity(scip);
15172  }
15173 
15174  if( !SCIPisInfinity(scip, lhs) )
15175  b = lhs/scale + nnegbinvars;
15176  else
15177  b = SCIPinfinity(scip);
15178 
15179  if( SCIPisEQ(scip, 1.0, b) )
15180  {
15181  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15182  SCIPdebugPrintCons(scip, cons, NULL);
15184 
15185  /* relax left hand side to prevent further classifications */
15186  lhs = -SCIPinfinity(scip);
15187  }
15188 
15189  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15190  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15191  continue;
15192  }
15193  }
15194 
15195  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15196  /* @todo If coefficients or rhs are not integral, we currently do not check
15197  * if the constraint could be scaled (finitely), such that they are.
15198  */
15199  {
15200  SCIP_Real b;
15201  SCIP_Bool unmatched;
15202 
15203  b = rhs;
15204  unmatched = FALSE;
15205  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15206  {
15207  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15208  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15209  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15210  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15211 
15212  if( SCIPisNegative(scip, consdata->vals[i]) )
15213  b -= consdata->vals[i];
15214  }
15215  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15216 
15217  if( !unmatched )
15218  {
15219  if( SCIPisEQ(scip, lhs, rhs) )
15220  {
15221  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15222  SCIPdebugPrintCons(scip, cons, NULL);
15223 
15225 
15226  continue;
15227  }
15228  else
15229  {
15230  SCIP_Bool matched;
15231 
15232  matched = FALSE;
15233  for( i = 0; i < consdata->nvars && !matched; i++ )
15234  {
15235  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15236  }
15237 
15238  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15239  SCIPdebugPrintCons(scip, cons, NULL);
15241  }
15242 
15243  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15244  if( SCIPisInfinity(scip, -lhs) )
15245  continue;
15246  else
15247  rhs = SCIPinfinity(scip);
15248  }
15249  }
15250 
15251  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15252  {
15253  SCIP_Real b;
15254  SCIP_Bool unmatched;
15255 
15256  unmatched = FALSE;
15257 
15258  b = rhs;
15259  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15260 
15261  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15262  {
15263  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15264  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15265  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15266  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15267  }
15268 
15269  if( !unmatched )
15270  {
15271  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15272  SCIPdebugPrintCons(scip, cons, NULL);
15274 
15275  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15276  if( SCIPisInfinity(scip, -lhs) )
15277  continue;
15278  else
15279  rhs = SCIPinfinity(scip);
15280  }
15281  }
15282 
15283  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15284  {
15285  SCIP_Bool unmatched;
15286 
15287  unmatched = FALSE;
15288  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15289  {
15290  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15291  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15292  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15293  unmatched = TRUE;
15294  }
15295 
15296  if( !unmatched )
15297  {
15298  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15299  SCIPdebugPrintCons(scip, cons, NULL);
15300  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15301 
15302  continue;
15303  }
15304  }
15305 
15306  /* no special structure detected */
15307  SCIPdebugMsg(scip, "classified as GENERAL: ");
15308  SCIPdebugPrintCons(scip, cons, NULL);
15309  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15310  }
15311 
15312  return SCIP_OKAY;
15313 }
15314 
15315 
15316 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15317 static
15318 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15319 { /*lint --e{715}*/
15320  int c;
15321 #ifdef SCIP_STATISTIC
15322  SCIP_CONSHDLRDATA* conshdlrdata;
15323  int ngoodconss;
15324  int nallconss;
15325 #endif
15326 
15327  /* delete all linear constraints that were upgraded to a more specific constraint type;
15328  * make sure, only active variables remain in the remaining constraints
15329  */
15330  assert(scip != NULL);
15331 
15332 #ifdef SCIP_STATISTIC
15333  /* count number of well behaved linear constraints */
15334  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15335  assert(conshdlrdata != NULL);
15336 
15337  ngoodconss = 0;
15338  nallconss = 0;
15339 
15340  for( c = 0; c < nconss; ++c )
15341  {
15342  SCIP_CONSDATA* consdata;
15343 
15344  if( SCIPconsIsDeleted(conss[c]) )
15345  continue;
15346 
15347  consdata = SCIPconsGetData(conss[c]);
15348  assert(consdata != NULL);
15349 
15350  if( consdata->upgraded )
15351  continue;
15352 
15353  nallconss++;
15354 
15355  consdataRecomputeMaxActivityDelta(scip, consdata);
15356 
15357  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15358  ngoodconss++;
15359  }
15360  if( nallconss )
15361  {
15362  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15363  }
15364 #endif
15365 
15366  for( c = 0; c < nconss; ++c )
15367  {
15368  SCIP_CONSDATA* consdata;
15369 
15370  if( SCIPconsIsDeleted(conss[c]) )
15371  continue;
15372 
15373  consdata = SCIPconsGetData(conss[c]);
15374  assert(consdata != NULL);
15375 
15376  if( consdata->upgraded )
15377  {
15378  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15379  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15380  */
15381  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15382  }
15383  else
15384  {
15385  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15386  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15387  }
15388  }
15389 
15390  return SCIP_OKAY;
15391 }
15392 
15393 
15394 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15395 static
15396 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15397 { /*lint --e{715}*/
15398  int c;
15399 
15400  assert(scip != NULL);
15401 
15402  /* release the rows of all constraints */
15403  for( c = 0; c < nconss; ++c )
15404  {
15405  SCIP_CONSDATA* consdata;
15406 
15407  consdata = SCIPconsGetData(conss[c]);
15408  assert(consdata != NULL);
15409 
15410  if( consdata->row != NULL )
15411  {
15412  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15413  }
15414  }
15415 
15416  /* if this is a restart, convert cutpool rows into linear constraints */
15417  if( restart )
15418  {
15419  int ncutsadded;
15420 
15421  ncutsadded = 0;
15422 
15423  /* create out of all active cuts in cutpool linear constraints */
15424  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15425 
15426  if( ncutsadded > 0 )
15427  {
15429  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15430  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15431  * line correctly
15432  */
15433  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "\n");
15434  }
15435  }
15436 
15437  return SCIP_OKAY;
15438 }
15439 
15440 
15441 /** constraint deactivation notification method of constraint handler */
15442 static
15443 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15444 { /*lint --e{715}*/
15445 
15446  if( SCIPconsIsDeleted(cons) )
15447  {
15448  SCIP_CONSHDLRDATA* conshdlrdata;
15449  SCIP_CONSDATA* consdata;
15450 
15451  assert(scip != NULL);
15452  assert(conshdlr != NULL);
15453  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15454 
15455  /* get constraint data */
15456  consdata = SCIPconsGetData(cons);
15457  assert(consdata != NULL);
15458 
15459  /* check for event handler */
15460  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15461  assert(conshdlrdata != NULL);
15462  assert(conshdlrdata->eventhdlr != NULL);
15463 
15464  /* free event data */
15465  if( consdata->eventdata != NULL )
15466  {
15467  /* drop bound change events of variables */
15468  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15469  }
15470  assert(consdata->eventdata == NULL);
15471  }
15472 
15473  return SCIP_OKAY;
15474 }
15475 
15476 
15477 /** frees specific constraint data */
15478 static
15479 SCIP_DECL_CONSDELETE(consDeleteLinear)
15480 { /*lint --e{715}*/
15481  assert(scip != NULL);
15482  assert(conshdlr != NULL);
15483  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15484 
15485  if( (*consdata)->eventdata != NULL )
15486  {
15487  SCIP_CONSHDLRDATA* conshdlrdata;
15488 
15489  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15490  assert(conshdlrdata != NULL);
15491 
15492  /* drop all events */
15493  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15494  assert((*consdata)->eventdata == NULL);
15495  }
15497  /* free linear constraint */
15498  SCIP_CALL( consdataFree(scip, consdata) );
15499 
15500  return SCIP_OKAY;
15501 }
15502 
15503 
15504 /** transforms constraint data into data belonging to the transformed problem */
15505 static
15506 SCIP_DECL_CONSTRANS(consTransLinear)
15507 { /*lint --e{715}*/
15508  SCIP_CONSDATA* sourcedata;
15509  SCIP_CONSDATA* targetdata;
15510 
15511  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15512 
15513  assert(scip != NULL);
15514  assert(conshdlr != NULL);
15515  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15516  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15517  assert(sourcecons != NULL);
15518  assert(targetcons != NULL);
15519 
15520  sourcedata = SCIPconsGetData(sourcecons);
15521  assert(sourcedata != NULL);
15522  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15524  /* create linear constraint data for target constraint */
15525  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15526 
15527  /* create target constraint */
15528  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15529  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15530  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15531  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15532  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15533 
15534  return SCIP_OKAY;
15535 }
15536 
15537 
15538 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15539 static
15540 SCIP_DECL_CONSINITLP(consInitlpLinear)
15541 { /*lint --e{715}*/
15542  int c;
15543 
15544  assert(scip != NULL);
15545  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15546 
15547  *infeasible = FALSE;
15548 
15549  for( c = 0; c < nconss && !(*infeasible); ++c )
15550  {
15551  assert(SCIPconsIsInitial(conss[c]));
15552  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15553  }
15554 
15555  return SCIP_OKAY;
15556 }
15558 
15559 /** separation method of constraint handler for LP solutions */
15560 static
15561 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15562 { /*lint --e{715}*/
15563  SCIP_CONSHDLRDATA* conshdlrdata;
15564  SCIP_Real loclowerbound;
15565  SCIP_Real glblowerbound;
15566  SCIP_Real cutoffbound;
15567  SCIP_Real maxbound;
15568  SCIP_Bool separatecards;
15569  SCIP_Bool cutoff;
15570  int c;
15571  int depth;
15572  int nrounds;
15573  int maxsepacuts;
15574  int ncuts;
15575 
15576  assert(scip != NULL);
15577  assert(conshdlr != NULL);
15578  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15579  assert(result != NULL);
15580 
15581  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15582  assert(conshdlrdata != NULL);
15583  depth = SCIPgetDepth(scip);
15584  nrounds = SCIPgetNSepaRounds(scip);
15585 
15586  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15587 
15588  *result = SCIP_DIDNOTRUN;
15589 
15590  /* only call the separator a given number of times at each node */
15591  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15592  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15593  return SCIP_OKAY;
15594 
15595  /* get the maximal number of cuts allowed in a separation round */
15596  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15597 
15598  /* check if we want to produce knapsack cardinality cuts at this node */
15599  loclowerbound = SCIPgetLocalLowerbound(scip);
15600  glblowerbound = SCIPgetLowerbound(scip);
15601  cutoffbound = SCIPgetCutoffbound(scip);
15602  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15603  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15604  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15605 
15606  *result = SCIP_DIDNOTFIND;
15607  ncuts = 0;
15608  cutoff = FALSE;
15609 
15610  /* check all useful linear constraints for feasibility */
15611  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15612  {
15613  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15614  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15615  }
15616 
15617  /* adjust return value */
15618  if( cutoff )
15619  *result = SCIP_CUTOFF;
15620  else if( ncuts > 0 )
15621  *result = SCIP_SEPARATED;
15622 
15623  /* combine linear constraints to get more cuts */
15624  /**@todo further cuts of linear constraints */
15625 
15626  return SCIP_OKAY;
15627 }
15628 
15629 
15630 /** separation method of constraint handler for arbitrary primal solutions */
15631 static
15632 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15633 { /*lint --e{715}*/
15634  SCIP_CONSHDLRDATA* conshdlrdata;
15635  int c;
15636  int depth;
15637  int nrounds;
15638  int maxsepacuts;
15639  int ncuts;
15640  SCIP_Bool cutoff;
15641 
15642  assert(scip != NULL);
15643  assert(conshdlr != NULL);
15644  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15645  assert(result != NULL);
15646 
15647  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15648  assert(conshdlrdata != NULL);
15649  depth = SCIPgetDepth(scip);
15650  nrounds = SCIPgetNSepaRounds(scip);
15651 
15652  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15653 
15654  *result = SCIP_DIDNOTRUN;
15655 
15656  /* only call the separator a given number of times at each node */
15657  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15658  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15659  return SCIP_OKAY;
15660 
15661  /* get the maximal number of cuts allowed in a separation round */
15662  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15663 
15664  *result = SCIP_DIDNOTFIND;
15665  ncuts = 0;
15666  cutoff = FALSE;
15667 
15668  /* check all useful linear constraints for feasibility */
15669  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15670  {
15671  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15672  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15673  }
15674 
15675  /* adjust return value */
15676  if( cutoff )
15677  *result = SCIP_CUTOFF;
15678  else if( ncuts > 0 )
15679  *result = SCIP_SEPARATED;
15680 
15681  /* combine linear constraints to get more cuts */
15682  /**@todo further cuts of linear constraints */
15683 
15684  return SCIP_OKAY;
15685 }
15686 
15687 
15688 /** constraint enforcing method of constraint handler for LP solutions */
15689 static
15690 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15691 { /*lint --e{715}*/
15692  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15693 
15694  return SCIP_OKAY;
15695 }
15696 
15697 /** constraint enforcing method of constraint handler for relaxation solutions */
15698 static
15699 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15700 { /*lint --e{715}*/
15701  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15702 
15703  return SCIP_OKAY;
15704 }
15705 
15706 /** constraint enforcing method of constraint handler for pseudo solutions */
15707 static
15708 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15709 { /*lint --e{715}*/
15710  SCIP_CONSHDLRDATA* conshdlrdata;
15711  SCIP_Bool checkrelmaxabs;
15712  SCIP_Bool violated;
15713  int c;
15714 
15715  assert(scip != NULL);
15716  assert(conshdlr != NULL);
15717  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15718  assert(result != NULL);
15719 
15720  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15721  assert(conshdlrdata != NULL);
15722 
15723  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15724 
15725  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15726 
15727  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
15728  if( objinfeasible )
15729  {
15730  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
15731 
15732  *result = SCIP_DIDNOTRUN;
15733  return SCIP_OKAY;
15734  }
15735 
15736  /* check all linear constraints for feasibility */
15737  violated = FALSE;
15738  for( c = 0; c < nconss && !violated; ++c )
15739  {
15740  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
15741  }
15742 
15743  if( violated )
15744  *result = SCIP_INFEASIBLE;
15745  else
15746  *result = SCIP_FEASIBLE;
15747 
15748  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15749 
15750  return SCIP_OKAY;
15751 }
15752 
15753 
15754 /** feasibility check method of constraint handler for integral solutions */
15755 static
15756 SCIP_DECL_CONSCHECK(consCheckLinear)
15757 { /*lint --e{715}*/
15758  SCIP_CONSHDLRDATA* conshdlrdata;
15759  SCIP_Bool checkrelmaxabs;
15760  int c;
15761 
15762  assert(scip != NULL);
15763  assert(conshdlr != NULL);
15764  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15765  assert(result != NULL);
15766 
15767  *result = SCIP_FEASIBLE;
15768 
15769  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15770  assert(conshdlrdata != NULL);
15771 
15772  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15774  /*debugMsg(scip, "Check method of linear constraints\n");*/
15775 
15776  /* check all linear constraints for feasibility */
15777  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
15778  {
15779  SCIP_Bool violated = FALSE;
15780  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
15781 
15782  if( violated )
15783  {
15784  *result = SCIP_INFEASIBLE;
15785 
15786  if( printreason )
15787  {
15788  SCIP_CONSDATA* consdata;
15789  SCIP_Real activity;
15790 
15791  consdata = SCIPconsGetData(conss[c]);
15792  assert( consdata != NULL);
15793 
15794  activity = consdataGetActivity(scip, consdata, sol);
15795 
15796  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
15797  SCIPinfoMessage(scip, NULL, ";\n");
15798 
15799  if( activity == SCIP_INVALID ) /*lint !e777*/
15800  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
15801  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
15802  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
15803  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
15804  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
15805  }
15806  }
15807  }
15808 
15809  return SCIP_OKAY;
15810 }
15811 
15812 
15813 /** domain propagation method of constraint handler */
15814 static
15815 SCIP_DECL_CONSPROP(consPropLinear)
15816 { /*lint --e{715}*/
15817  SCIP_CONSHDLRDATA* conshdlrdata;
15818  SCIP_Bool rangedrowpropagation = FALSE;
15819  SCIP_Bool tightenbounds;
15820  SCIP_Bool cutoff;
15821 
15822  int nchgbds;
15823  int i;
15824 
15825  assert(scip != NULL);
15826  assert(conshdlr != NULL);
15827  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15828  assert(result != NULL);
15829 
15830  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15831  assert(conshdlrdata != NULL);
15833  /*debugMsg(scip, "Prop method of linear constraints\n");*/
15834 
15835  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
15836  if( SCIPinProbing(scip) )
15837  tightenbounds = TRUE;
15838  else
15839  {
15840  int depth;
15841  int propfreq;
15842  int tightenboundsfreq;
15843  int rangedrowfreq;
15844 
15845  depth = SCIPgetDepth(scip);
15846  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
15847  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
15848  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
15849  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
15850 
15851  /* check if we want to do ranged row propagation */
15852  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
15853  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
15854  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
15855  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
15856  rangedrowpropagation = rangedrowpropagation && (depth % rangedrowfreq == 0);
15857  }
15858 
15859  cutoff = FALSE;
15860  nchgbds = 0;
15861 
15862  /* process constraints marked for propagation */
15863  for( i = 0; i < nmarkedconss && !cutoff; i++ )
15864  {
15865  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
15866  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
15867  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
15868  }
15869 
15870  /* adjust result code */
15871  if( cutoff )
15872  *result = SCIP_CUTOFF;
15873  else if( nchgbds > 0 )
15874  *result = SCIP_REDUCEDDOM;
15875  else
15876  *result = SCIP_DIDNOTFIND;
15877 
15878  return SCIP_OKAY;
15879 }
15880 
15881 
15882 #define MAXCONSPRESOLROUNDS 10
15883 /** presolving method of constraint handler */
15884 static
15885 SCIP_DECL_CONSPRESOL(consPresolLinear)
15886 { /*lint --e{715}*/
15887  SCIP_CONSHDLRDATA* conshdlrdata;
15888  SCIP_CONS* cons;
15889  SCIP_CONSDATA* consdata;
15890  SCIP_Real minactivity;
15891  SCIP_Real maxactivity;
15892  SCIP_Bool minactisrelax;
15893  SCIP_Bool maxactisrelax;
15894  SCIP_Bool cutoff;
15895  int oldnfixedvars;
15896  int oldnaggrvars;
15897  int oldnchgbds;
15898  int oldndelconss;
15899  int oldnupgdconss;
15900  int oldnchgcoefs;
15901  int oldnchgsides;
15902  int firstchange;
15903  int firstupgradetry;
15904  int c;
15905 
15906  assert(scip != NULL);
15907  assert(conshdlr != NULL);
15908  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15909  assert(result != NULL);
15910 
15911  /*debugMsg(scip, "Presol method of linear constraints\n");*/
15912 
15913  /* remember old preprocessing counters */
15914  cutoff = FALSE;
15915  oldnfixedvars = *nfixedvars;
15916  oldnaggrvars = *naggrvars;
15917  oldnchgbds = *nchgbds;
15918  oldndelconss = *ndelconss;
15919  oldnupgdconss = *nupgdconss;
15920  oldnchgcoefs = *nchgcoefs;
15921  oldnchgsides = *nchgsides;
15922 
15923  /* get constraint handler data */
15924  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15925  assert(conshdlrdata != NULL);
15926 
15927  /* process single constraints */
15928  firstchange = INT_MAX;
15929  firstupgradetry = INT_MAX;
15930  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
15931  {
15932  int npresolrounds;
15933  SCIP_Bool infeasible;
15934 
15935  infeasible = FALSE;
15936 
15937  cons = conss[c];
15938  assert(SCIPconsIsActive(cons));
15939  consdata = SCIPconsGetData(cons);
15940  assert(consdata != NULL);
15941 
15942  if( consdata->eventdata == NULL )
15943  {
15944  /* catch bound change events of variables */
15945  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15946  assert(consdata->eventdata != NULL);
15947  }
15948 
15949  /* constraint should not be already presolved in the initial round */
15950  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
15951  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
15952  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
15953  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
15954 
15955  /* incorporate fixings and aggregations in constraint */
15956  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
15957 
15958  if( infeasible )
15959  {
15960  SCIPdebugMsg(scip, " -> infeasible fixing\n");
15961  cutoff = TRUE;
15962  break;
15963  }
15964 
15965  assert(consdata->removedfixings);
15966 
15967  /* we can only presolve linear constraints, that are not modifiable */
15968  if( SCIPconsIsModifiable(cons) )
15969  continue;
15970 
15971  /* remember the first changed constraint to begin the next aggregation round with */
15972  if( firstchange == INT_MAX && consdata->changed )
15973  firstchange = c;
15974 
15975  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
15976  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
15977  firstupgradetry = c;
15978 
15979  /* check, if constraint is already preprocessed */
15980  if( consdata->presolved )
15981  continue;
15982 
15983  assert(SCIPconsIsActive(cons));
15984 
15985  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
15986  SCIPdebugPrintCons(scip, cons, NULL);
15987 
15988  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
15989  * to avoid nearly infinite cycling due to very small bound changes)
15990  */
15991  npresolrounds = 0;
15992  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
15993  {
15994  assert(!cutoff);
15995  npresolrounds++;
15996 
15997  /* mark constraint being presolved and propagated */
15998  consdata->presolved = TRUE;
15999  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16000 
16001  /* normalize constraint */
16002  SCIP_CALL( normalizeCons(scip, cons) );
16003 
16004  /* tighten left and right hand side due to integrality */
16005  SCIP_CALL( tightenSides(scip, cons, nchgsides) );
16006 
16007  /* check bounds */
16008  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16009  {
16010  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16011  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16012  cutoff = TRUE;
16013  break;
16014  }
16015 
16016  /* tighten variable's bounds */
16017  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16018  if( cutoff )
16019  break;
16020 
16021  /* check for fixed variables */
16022  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16023  if( cutoff )
16024  break;
16025 
16026  /* check constraint for infeasibility and redundancy */
16027  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
16028  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16029  {
16030  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16031  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16032  cutoff = TRUE;
16033  break;
16034  }
16035  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16036  {
16037  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16038  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16039  SCIP_CALL( SCIPdelCons(scip, cons) );
16040  assert(!SCIPconsIsActive(cons));
16041 
16042  if( !consdata->upgraded )
16043  (*ndelconss)++;
16044  break;
16045  }
16046  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
16047  {
16048  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16049  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16050  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16051  if( !consdata->upgraded )
16052  (*nchgsides)++;
16053  }
16054  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16055  {
16056  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16057  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16058  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16059  if( !consdata->upgraded )
16060  (*nchgsides)++;
16061  }
16062  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
16063 
16064  /* handle empty constraint */
16065  if( consdata->nvars == 0 )
16066  {
16067  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16068  {
16069  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16070  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16071  cutoff = TRUE;
16072  }
16073  else
16074  {
16075  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16076  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16077  SCIP_CALL( SCIPdelCons(scip, cons) );
16078  assert(!SCIPconsIsActive(cons));
16079 
16080  if( !consdata->upgraded )
16081  (*ndelconss)++;
16082  }
16083  break;
16084  }
16085 
16086  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16087  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16088 
16089  /* try to simplify inequalities */
16090  if( conshdlrdata->simplifyinequalities )
16091  {
16092  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides) );
16093  }
16094 
16095  /* aggregation variable in equations */
16096  if( conshdlrdata->aggregatevariables )
16097  {
16098  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16099  if( cutoff )
16100  break;
16101  }
16102  }
16103 
16104  if( !cutoff && !SCIPisStopped(scip) )
16105  {
16106  /* perform ranged row propagation */
16107  if( conshdlrdata->rangedrowpropagation )
16108  {
16109  int lastnfixedvars;
16110 
16111  lastnfixedvars = *nfixedvars;
16112 
16113  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16114  if( !cutoff )
16115  {
16116  if( lastnfixedvars < *nfixedvars )
16117  {
16118  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16119  }
16120  }
16121  }
16122 
16123  /* extract cliques from constraint */
16124  if( !cutoff && SCIPconsIsActive(cons) )
16125  {
16126  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16127  nfixedvars, nchgbds, &cutoff) );
16128 
16129  /* check if the constraint got redundant or infeasible */
16130  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16131  {
16132  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16133  {
16134  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16135  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16136  cutoff = TRUE;
16137  }
16138  else
16139  {
16140  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16141  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16142  SCIP_CALL( SCIPdelCons(scip, cons) );
16143  assert(!SCIPconsIsActive(cons));
16144 
16145  if( !consdata->upgraded )
16146  (*ndelconss)++;
16147  }
16148  }
16149  }
16150 
16151  /* convert special equalities */
16152  if( !cutoff && SCIPconsIsActive(cons) )
16153  {
16154  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16155  }
16156 
16157  /* apply dual presolving for variables that appear in only one constraint */
16158  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
16159  {
16160  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16161  }
16162 
16163  /* check if an inequality is parallel to the objective function */
16164  if( !cutoff && SCIPconsIsActive(cons) )
16165  {
16166  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16167  }
16168 
16169  /* remember the first changed constraint to begin the next aggregation round with */
16170  if( firstchange == INT_MAX && consdata->changed )
16171  firstchange = c;
16172 
16173  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16174  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16175  firstupgradetry = c;
16176  }
16177 
16178  /* singleton column stuffing */
16179  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16180  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowDualReds(scip) )
16181  {
16182  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16183  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16184 
16185  /* handle empty constraint */
16186  if( consdata->nvars == 0 )
16187  {
16188  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16189  {
16190  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16191  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16192  cutoff = TRUE;
16193  }
16194  else
16195  {
16196  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16197  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16198  SCIP_CALL( SCIPdelCons(scip, cons) );
16199  assert(!SCIPconsIsActive(cons));
16200 
16201  if( !consdata->upgraded )
16202  (*ndelconss)++;
16203  }
16204  break;
16205  }
16206  }
16207  }
16208 
16209  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16210  * only apply this expensive procedure in exhaustive presolving timing
16211  */
16212  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16213  {
16214  assert(firstchange >= 0);
16215 
16216  if( firstchange < nconss && conshdlrdata->presolusehashing )
16217  {
16218  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16219  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16220  ndelconss, nchgsides) );
16221  }
16222 
16223  if( firstchange < nconss && conshdlrdata->presolpairwise )
16224  {
16225  SCIP_CONS** usefulconss;
16226  int nusefulconss;
16227  int firstchangenew;
16228  SCIP_Longint npaircomparisons;
16229 
16230  npaircomparisons = 0;
16231  oldndelconss = *ndelconss;
16232  oldnchgsides = *nchgsides;
16233  oldnchgcoefs = *nchgcoefs;
16234 
16235  /* allocate temporary memory */
16236  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16237 
16238  nusefulconss = 0;
16239  firstchangenew = -1;
16240  for( c = 0; c < nconss; ++c )
16241  {
16242  /* update firstchange */
16243  if( c == firstchange )
16244  firstchangenew = nusefulconss;
16245 
16246  /* ignore inactive and modifiable constraints */
16247  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16248  continue;
16249 
16250  usefulconss[nusefulconss] = conss[c];
16251  ++nusefulconss;
16252  }
16253  firstchange = firstchangenew;
16254  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16255 
16256  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16257  {
16258  /* constraint has become inactive or modifiable during pairwise presolving */
16259  if( usefulconss[c] == NULL )
16260  continue;
16261 
16262  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16263 
16264  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16265  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16266  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16267 
16268  if( npaircomparisons > conshdlrdata->nmincomparisons )
16269  {
16270  assert(npaircomparisons > 0);
16271  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16272  break;
16273  oldndelconss = *ndelconss;
16274  oldnchgsides = *nchgsides;
16275  oldnchgcoefs = *nchgcoefs;
16276  npaircomparisons = 0;
16277  }
16278  }
16279  /* free temporary memory */
16280  SCIPfreeBufferArray(scip, &usefulconss);
16281  }
16282  }
16283 
16284  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16285  * in linear constraints and we therefore have full information about it
16286  */
16287  if( !cutoff && firstupgradetry < nconss
16288  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16289  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16290  )
16291  {
16292  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) && !SCIPisStopped(scip) )
16293  {
16294  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16295  }
16296  }
16297 
16298  /* try to upgrade constraints into a more specific constraint type;
16299  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16300  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16301  */
16302  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16303  {
16304  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16305  {
16306  cons = conss[c];
16307 
16308  /* don't upgrade modifiable constraints */
16309  if( SCIPconsIsModifiable(cons) )
16310  continue;
16311 
16312  consdata = SCIPconsGetData(cons);
16313  assert(consdata != NULL);
16314 
16315  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16316  if( consdata->upgradetried )
16317  continue;
16318  /* @todo force that upgrade will be performed later? */
16319  if( !consdata->presolved )
16320  continue;
16321 
16322  consdata->upgradetried = TRUE;
16323  if( SCIPconsIsActive(cons) )
16324  {
16325  SCIP_CONS* upgdcons;
16326 
16327  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16328  if( upgdcons != NULL )
16329  {
16330  /* add the upgraded constraint to the problem */
16331  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16332  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16333  (*nupgdconss)++;
16334 
16335  /* mark the linear constraint being upgraded and to be removed after presolving;
16336  * don't delete it directly, because it may help to preprocess other linear constraints
16337  */
16338  assert(!consdata->upgraded);
16339  consdata->upgraded = TRUE;
16340 
16341  /* delete upgraded inequalities immediately;
16342  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16343  */
16344  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16345  || !conshdlrdata->presolpairwise
16346  || (conshdlrdata->maxaggrnormscale == 0.0) )
16347  {
16348  SCIP_CALL( SCIPdelCons(scip, cons) );
16349  }
16350  }
16351  }
16352  }
16353  }
16354 
16355  /* return the correct result code */
16356  if( cutoff )
16357  *result = SCIP_CUTOFF;
16358  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16359  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16360  *result = SCIP_SUCCESS;
16361  else
16362  *result = SCIP_DIDNOTFIND;
16363 
16364  return SCIP_OKAY;
16365 }
16366 
16367 
16368 /** propagation conflict resolving method of constraint handler */
16369 static
16370 SCIP_DECL_CONSRESPROP(consRespropLinear)
16371 { /*lint --e{715}*/
16372 
16373  assert(scip != NULL);
16374  assert(cons != NULL);
16375  assert(result != NULL);
16376 
16377  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16378 
16379  return SCIP_OKAY;
16380 }
16381 
16382 
16383 /** variable rounding lock method of constraint handler */
16384 static
16385 SCIP_DECL_CONSLOCK(consLockLinear)
16386 { /*lint --e{715}*/
16387  SCIP_CONSDATA* consdata;
16388  SCIP_Bool haslhs;
16389  SCIP_Bool hasrhs;
16390  int i;
16391 
16392  assert(scip != NULL);
16393  assert(cons != NULL);
16394  consdata = SCIPconsGetData(cons);
16395  assert(consdata != NULL);
16396 
16397  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16398  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16399 
16400  /* update rounding locks of every single variable */
16401  for( i = 0; i < consdata->nvars; ++i )
16402  {
16403  if( SCIPisPositive(scip, consdata->vals[i]) )
16404  {
16405  if( haslhs )
16406  {
16407  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16408  }
16409  if( hasrhs )
16410  {
16411  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16412  }
16413  }
16414  else
16415  {
16416  if( haslhs )
16417  {
16418  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16419  }
16420  if( hasrhs )
16421  {
16422  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16423  }
16424  }
16425  }
16426 
16427  return SCIP_OKAY;
16428 }
16429 
16430 
16431 /** variable deletion method of constraint handler */
16432 static
16433 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16434 {
16435  assert(scip != NULL);
16436  assert(conshdlr != NULL);
16437  assert(conss != NULL || nconss == 0);
16438 
16439  if( nconss > 0 )
16440  {
16441  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16442  }
16443 
16444  return SCIP_OKAY;
16445 }
16446 
16447 /** constraint display method of constraint handler */
16448 static
16449 SCIP_DECL_CONSPRINT(consPrintLinear)
16450 { /*lint --e{715}*/
16451  assert(scip != NULL);
16452  assert(conshdlr != NULL);
16453  assert(cons != NULL);
16454 
16455  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16456 
16457  return SCIP_OKAY;
16458 }
16459 
16460 /** constraint copying method of constraint handler */
16461 static
16462 SCIP_DECL_CONSCOPY(consCopyLinear)
16463 { /*lint --e{715}*/
16464  SCIP_VAR** sourcevars;
16465  SCIP_Real* sourcecoefs;
16466  const char* consname;
16467  int nvars;
16468 
16469  assert(scip != NULL);
16470  assert(sourcescip != NULL);
16471  assert(sourcecons != NULL);
16472 
16473  /* get variables and coefficients of the source constraint */
16474  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16475  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16476  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16477 
16478  if( name != NULL )
16479  consname = name;
16480  else
16481  consname = SCIPconsGetName(sourcecons);
16482 
16483  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16484  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16485  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16486  assert(cons != NULL || *valid == FALSE);
16487 
16488  /* @todo should also the checkabsolute flag of the constraint be copied? */
16489 
16490  return SCIP_OKAY;
16491 }
16492 
16493 /* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
16494  * except for ranged rows for which exactly two operators '<=' must be present
16495  */
16496 static
16498  const char* str, /**< null terminated input string */
16499  char** firstoperator, /**< pointer to store the string starting at the first operator */
16500  char** secondoperator, /**< pointer to store the string starting at the second operator */
16501  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16502  )
16503 {
16504  char* curr;
16505 
16506  assert(str != NULL);
16507  assert(firstoperator != NULL);
16508  assert(secondoperator != NULL);
16509 
16510  *firstoperator = NULL;
16511  *secondoperator = NULL;
16512 
16513  curr = (char*)str;
16514  *success = TRUE;
16515 
16516  /* loop over the input string to find all operators */
16517  while( *curr && *success )
16518  {
16519  SCIP_Bool found = FALSE;
16520  int increment = 1;
16521 
16522  /* try if we found a possible operator */
16523  switch( *curr )
16524  {
16525  case '<':
16526  case '=':
16527  case '>':
16528 
16529  /* check if the two characters curr[0,1] form an operator together */
16530  if( curr[1] == '=' )
16531  {
16532  found = TRUE;
16533 
16534  /* update increment to continue after this operator */
16535  increment = 2;
16536  }
16537  break;
16538  case '[':
16539  if( strncmp(curr, "[free]", 6) == 0 )
16540  {
16541  found = TRUE;
16542 
16543  /* update increment to continue after this operator */
16544  increment = 6;
16545  }
16546  break;
16547  default:
16548  break;
16549 
16550  }
16551 
16552  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16553  if( found )
16554  {
16555  if( *firstoperator == NULL )
16556  {
16557  *firstoperator = curr;
16558  }
16559  else
16560  {
16561  if( *secondoperator != NULL )
16562  {
16563  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16564  *success = FALSE;
16565  }
16566  else if( strncmp(*firstoperator, "<=", 2) != 0 )
16567  {
16568  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16569  *success = FALSE;
16570  }
16571  else if( strncmp(curr, "<=", 2) != 0 )
16572  {
16573  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16574  *success = FALSE;
16575  }
16576 
16577  *secondoperator = curr;
16578  }
16579  }
16580 
16581  curr += increment;
16582  }
16583 
16584  /* check if we did find at least one operator */
16585  if( *success )
16586  {
16587  if( *firstoperator == NULL )
16588  {
16589  SCIPerrorMessage("Could not find any operator in line %s\n", str);
16590  *success = FALSE;
16591  }
16592  }
16593 
16594  return SCIP_OKAY;
16595 }
16596 
16597 /** constraint parsing method of constraint handler */
16598 static
16599 SCIP_DECL_CONSPARSE(consParseLinear)
16600 { /*lint --e{715}*/
16601  SCIP_VAR** vars;
16602  SCIP_Real* coefs;
16603  int nvars;
16604  int coefssize;
16605  int requsize;
16606  SCIP_Real lhs;
16607  SCIP_Real rhs;
16608  char* endptr;
16609  char* firstop;
16610  char* secondop;
16611  SCIP_Bool operatorsuccess;
16612  char* lhsstrptr;
16613  char* rhsstrptr;
16614  char* varstrptr;
16615 
16616  assert(scip != NULL);
16617  assert(success != NULL);
16618  assert(str != NULL);
16619  assert(name != NULL);
16620  assert(cons != NULL);
16621 
16622  /* set left and right hand side to their default values */
16623  lhs = -SCIPinfinity(scip);
16624  rhs = SCIPinfinity(scip);
16625 
16626  (*success) = FALSE;
16627 
16628  /* return of string empty */
16629  if( !*str )
16630  return SCIP_OKAY;
16631 
16632  /* ignore whitespace */
16633  while( isspace((unsigned char)*str) )
16634  ++str;
16635 
16636  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16637  * and the special word [free]
16638  */
16639  SCIP_CALL( findOperators(str, &firstop, &secondop, &operatorsuccess) );
16640 
16641  /* if the grammar is not valid for parsing a linear constraint, return */
16642  if( ! operatorsuccess )
16643  return SCIP_OKAY;
16644 
16645  varstrptr = (char *)str;
16646  lhsstrptr = rhsstrptr = NULL;
16647  assert(firstop != NULL);
16648 
16649  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16650  switch( *firstop )
16651  {
16652  case '<':
16653  assert(firstop[1] == '=');
16654  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16655  if( secondop != NULL )
16656  {
16657  assert(secondop[0] == '<' && secondop[1] == '=');
16658  lhsstrptr = (char *)str;
16659  varstrptr = firstop + 2;
16660  rhsstrptr = secondop + 2;
16661  }
16662  else
16663  {
16664  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16665  lhsstrptr = NULL;
16666  varstrptr = (char *)str;
16667  rhsstrptr = firstop + 2;
16668  }
16669  break;
16670  case '>':
16671  assert(firstop[1] == '=');
16672  assert(secondop == NULL);
16673  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16674  lhsstrptr = firstop + 2;
16675  break;
16676  case '=':
16677  assert(firstop[1] == '=');
16678  assert(secondop == NULL);
16679  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16680  rhsstrptr = firstop + 2;
16681  lhsstrptr = firstop + 2;
16682  break;
16683  case '[':
16684  assert(strncmp(firstop, "[free]", 6) == 0);
16685  assert(secondop == NULL);
16686  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16687  break;
16688  default:
16689  /* it should not be possible that a different character appears in that position */
16690  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16691  return SCIP_READERROR;
16692  }
16693 
16694  /* parse left hand side, if necessary */
16695  if( lhsstrptr != NULL )
16696  {
16697  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16698  {
16699  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16700  return SCIP_OKAY;
16701  }
16702 
16703  /* in case of an equation, assign the left also to the right hand side */
16704  if( rhsstrptr == lhsstrptr )
16705  rhs = lhs;
16706  }
16707 
16708  /* parse right hand side, if different from left hand side */
16709  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
16710  {
16711  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
16712  {
16713  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
16714  return SCIP_OKAY;
16715  }
16716  }
16717 
16718  /* initialize buffers for storing the variables and coefficients */
16719  coefssize = 100;
16720  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
16721  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
16722 
16723  assert(varstrptr != NULL);
16724 
16725  /* parse linear sum to get variables and coefficients */
16726  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16727 
16728  if( *success && requsize > coefssize )
16729  {
16730  /* realloc buffers and try again */
16731  coefssize = requsize;
16732  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
16733  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
16734 
16735  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16736  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
16737  }
16738 
16739  if( !*success )
16740  {
16741  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
16742  }
16743  else
16744  {
16745  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
16746  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
16747  }
16748 
16749  SCIPfreeBufferArray(scip, &coefs);
16750  SCIPfreeBufferArray(scip, &vars);
16751 
16752  return SCIP_OKAY;
16753 }
16754 
16755 
16756 /** constraint method of constraint handler which returns the variables (if possible) */
16757 static
16758 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
16759 { /*lint --e{715}*/
16760  SCIP_CONSDATA* consdata;
16761 
16762  consdata = SCIPconsGetData(cons);
16763  assert(consdata != NULL);
16764 
16765  if( varssize < consdata->nvars )
16766  (*success) = FALSE;
16767  else
16768  {
16769  assert(vars != NULL);
16770 
16771  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
16772  (*success) = TRUE;
16773  }
16774 
16775  return SCIP_OKAY;
16776 }
16777 
16778 /**! [Callback for the number of variables]*/
16779 /** constraint method of constraint handler which returns the number of variables (if possible) */
16780 static
16781 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
16782 { /*lint --e{715}*/
16783  SCIP_CONSDATA* consdata;
16784 
16785  consdata = SCIPconsGetData(cons);
16786  assert(consdata != NULL);
16787 
16788  (*nvars) = consdata->nvars;
16789  (*success) = TRUE;
16790 
16791  return SCIP_OKAY;
16792 }
16793 /**! [Callback for the number of variables]*/
16794 
16795 /*
16796  * Callback methods of event handler
16797  */
16799 static
16800 SCIP_DECL_EVENTEXEC(eventExecLinear)
16801 { /*lint --e{715}*/
16802  SCIP_CONS* cons;
16803  SCIP_CONSDATA* consdata;
16804  SCIP_VAR* var;
16805  SCIP_EVENTTYPE eventtype;
16806 
16807  assert(scip != NULL);
16808  assert(eventhdlr != NULL);
16809  assert(eventdata != NULL);
16810  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
16811  assert(event != NULL);
16812 
16813  cons = eventdata->cons;
16814  assert(cons != NULL);
16815  consdata = SCIPconsGetData(cons);
16816  assert(consdata != NULL);
16818  /* we can skip events droped for deleted constraints */
16819  if( SCIPconsIsDeleted(cons) )
16820  return SCIP_OKAY;
16821 
16822  eventtype = SCIPeventGetType(event);
16823  var = SCIPeventGetVar(event);
16824 
16825  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
16826  {
16827  SCIP_Real oldbound;
16828  SCIP_Real newbound;
16829  SCIP_Real val;
16830  int varpos;
16831 
16832  varpos = eventdata->varpos;
16833  assert(0 <= varpos && varpos < consdata->nvars);
16834  oldbound = SCIPeventGetOldbound(event);
16835  newbound = SCIPeventGetNewbound(event);
16836  assert(var != NULL);
16837  assert(consdata->vars[varpos] == var);
16838  val = consdata->vals[varpos];
16839 
16840  /* we only need to update the activities if the constraint is active,
16841  * otherwise we mark them to be invalid
16842  */
16843  if( SCIPconsIsActive(cons) )
16844  {
16845  /* update the activity values */
16846  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
16847  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
16848  else
16849  {
16850  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
16851  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
16852  }
16853  }
16854  else
16855  consdataInvalidateActivities(consdata);
16856 
16857  consdata->presolved = FALSE;
16858  consdata->rangedrowpropagated = 0;
16859 
16860  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
16861  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
16862  {
16863  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
16864 
16865  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16866  if( consdata->maxactdeltavar == var )
16867  {
16868  consdata->maxactdelta = SCIP_INVALID;
16869  consdata->maxactdeltavar = NULL;
16870  }
16871 
16872  /* check whether bound tightening might now be successful */
16873  if( consdata->boundstightened > 0)
16874  {
16875  switch( eventtype )
16876  {
16878  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
16879  consdata->boundstightened = 0;
16880  break;
16882  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
16883  consdata->boundstightened = 0;
16884  break;
16885  default:
16886  SCIPerrorMessage("invalid event type %d\n", eventtype);
16887  return SCIP_INVALIDDATA;
16888  }
16889  }
16890  }
16891  /* update maximal activity delta if a bound was relaxed */
16892  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
16893  {
16894  SCIP_Real lb;
16895  SCIP_Real ub;
16896  SCIP_Real domain;
16897  SCIP_Real delta;
16898 
16899  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
16900 
16901  lb = SCIPvarGetLbLocal(var);
16902  ub = SCIPvarGetUbLocal(var);
16903 
16904  domain = ub - lb;
16905  delta = REALABS(val) * domain;
16906 
16907  if( delta > consdata->maxactdelta )
16908  {
16909  consdata->maxactdelta = delta;
16910  consdata->maxactdeltavar = var;
16911  }
16912  }
16913  }
16914  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
16915  {
16916  /* we want to remove the fixed variable */
16917  consdata->presolved = FALSE;
16918  consdata->removedfixings = FALSE;
16919  consdata->rangedrowpropagated = 0;
16920 
16921  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16922  if( consdata->maxactdeltavar == var )
16923  {
16924  consdata->maxactdelta = SCIP_INVALID;
16925  consdata->maxactdeltavar = NULL;
16926  }
16927  }
16928 
16929  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
16930  {
16931  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
16932  assert(SCIPvarGetNLocksDown(var) <= 1);
16933  assert(SCIPvarGetNLocksUp(var) <= 1);
16934  consdata->presolved = FALSE;
16935  }
16936  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
16937  {
16938  SCIP_Real oldbound;
16939  SCIP_Real newbound;
16940  SCIP_Real val;
16941  int varpos;
16942 
16943  varpos = eventdata->varpos;
16944  assert(0 <= varpos && varpos < consdata->nvars);
16945  oldbound = SCIPeventGetOldbound(event);
16946  newbound = SCIPeventGetNewbound(event);
16947  assert(var != NULL);
16948  assert(consdata->vars[varpos] == var);
16949  val = consdata->vals[varpos];
16950 
16951  consdata->rangedrowpropagated = 0;
16952 
16953  /* update the activity values */
16954  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
16955  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
16956  else
16957  {
16958  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
16959  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
16960  }
16961  }
16962  else
16963  {
16964  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
16965  consdata->varsdeleted = TRUE;
16966  }
16967 
16968  return SCIP_OKAY;
16969 }
16970 
16971 
16972 /*
16973  * Callback methods of conflict handler
16974  */
16975 
16976 static
16977 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
16978 { /*lint --e{715}*/
16979  SCIP_VAR** vars;
16980  SCIP_Real* vals;
16981  SCIP_Real lhs;
16982  int i;
16983 
16984  assert(scip != NULL);
16985  assert(conflicthdlr != NULL);
16986  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
16987  assert(bdchginfos != NULL || nbdchginfos == 0);
16988  assert(result != NULL);
16989 
16990  /* don't process already resolved conflicts */
16991  if( resolved )
16992  {
16993  *result = SCIP_DIDNOTRUN;
16994  return SCIP_OKAY;
16995  }
16996 
16997  *result = SCIP_DIDNOTFIND;
16998 
16999  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17000  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17001  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17002  lhs = 1.0;
17003  for( i = 0; i < nbdchginfos; ++i )
17004  {
17005  assert(bdchginfos != NULL);
17006 
17007  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17008 
17009  /* we can only treat binary variables */
17010  /**@todo extend linear conflict constraints to some non-binary cases */
17011  if( !SCIPvarIsBinary(vars[i]) )
17012  break;
17013 
17014  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17015  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17016  vals[i] = 1.0;
17017  else
17018  {
17019  vals[i] = -1.0;
17020  lhs -= 1.0;
17021  }
17022  }
17023 
17024  if( i == nbdchginfos )
17025  {
17026  SCIP_CONS* cons;
17027  SCIP_CONS* upgdcons;
17028  char consname[SCIP_MAXSTRLEN];
17029 
17030  /* create a constraint out of the conflict set */
17031  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17032  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17033  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17034 
17035  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17036  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17037  if( upgdcons != NULL )
17038  {
17039  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17040  cons = upgdcons;
17041  }
17042 
17043  /* add conflict to SCIP */
17044  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17045 
17046  *result = SCIP_CONSADDED;
17047  }
17048 
17049  /* free temporary memory */
17050  SCIPfreeBufferArray(scip, &vals);
17051  SCIPfreeBufferArray(scip, &vars);
17052 
17053  return SCIP_OKAY;
17054 }
17055 
17056 
17057 /*
17058  * Quadratic constraint upgrading
17059  */
17060 
17061 
17062 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
17063  */
17064 static
17065 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
17066 { /*lint --e{715}*/
17067  SCIP_CONSDATA* upgdconsdata;
17068 
17069  assert(scip != NULL);
17070  assert(cons != NULL);
17071  assert(nupgdconss != NULL);
17072  assert(upgdconss != NULL);
17073 
17074  *nupgdconss = 0;
17075 
17076  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
17077  SCIPdebugPrintCons(scip, cons, NULL);
17078 
17079  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
17080  return SCIP_OKAY;
17081  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
17082  return SCIP_OKAY;
17083 
17084  if( upgdconsssize < 1 )
17085  {
17086  /* signal that we need more memory */
17087  *nupgdconss = -1;
17088  return SCIP_OKAY;
17089  }
17090 
17091  *nupgdconss = 1;
17092  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17093  SCIPgetNLinearVarsQuadratic(scip, cons),
17094  SCIPgetLinearVarsQuadratic(scip, cons),
17095  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
17096  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
17100  SCIPconsIsStickingAtNode(cons)) );
17101 
17102  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17103  assert(upgdconsdata != NULL);
17104 
17105  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original quadratic constraint */
17106  upgdconsdata->checkabsolute = TRUE;
17107 
17108  SCIPdebugMsg(scip, "created linear constraint:\n");
17109  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17110 
17111  return SCIP_OKAY;
17112 }
17113 
17114 /** tries to upgrade a nonlinear constraint into a linear constraint */
17115 static
17116 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17117 {
17118  SCIP_CONSDATA* upgdconsdata;
17119 
17120  assert(nupgdconss != NULL);
17121  assert(upgdconss != NULL);
17122 
17123  *nupgdconss = 0;
17124 
17125  /* no interest in nonlinear constraints */
17126  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
17127  return SCIP_OKAY;
17128 
17129  /* no interest in constant constraints */
17130  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
17131  return SCIP_OKAY;
17132 
17133  if( upgdconsssize < 1 )
17134  {
17135  /* request larger upgdconss array */
17136  *nupgdconss = -1;
17137  return SCIP_OKAY;
17138  }
17139 
17140  *nupgdconss = 1;
17141  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17143  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
17147  SCIPconsIsStickingAtNode(cons)) );
17148 
17149  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17150  assert(upgdconsdata != NULL);
17151 
17152  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17153  upgdconsdata->checkabsolute = TRUE;
17154 
17155  SCIPdebugMsg(scip, "created linear constraint:\n");
17156  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17157 
17158  return SCIP_OKAY;
17159 }
17160 
17161 /*
17162  * constraint specific interface methods
17163  */
17164 
17165 /** creates the handler for linear constraints and includes it in SCIP */
17167  SCIP* scip /**< SCIP data structure */
17168  )
17169 {
17170  SCIP_CONSHDLRDATA* conshdlrdata;
17171  SCIP_CONSHDLR* conshdlr;
17172  SCIP_EVENTHDLR* eventhdlr;
17173  SCIP_CONFLICTHDLR* conflicthdlr;
17174 
17175  assert(scip != NULL);
17176 
17177  /* create event handler for bound change events */
17179  eventExecLinear, NULL) );
17180 
17181  /* create conflict handler for linear constraints */
17183  conflictExecLinear, NULL) );
17184 
17185  /* create constraint handler data */
17186  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17187 
17188  /* include constraint handler */
17191  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17192  conshdlrdata) );
17193 
17194  assert(conshdlr != NULL);
17195 
17196  /* set non-fundamental callbacks via specific setter functions */
17197  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17198  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17199  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17200  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17201  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17202  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17203  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17204  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17205  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17206  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17207  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17208  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17209  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17210  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17211  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17212  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17214  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17215  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17217  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17218  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17219 
17220  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
17221  {
17222  /* include function that upgrades quadratic constraint to linear constraints */
17224  }
17225 
17226  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17227  {
17228  /* include the linear constraint upgrade in the nonlinear constraint handler */
17229  SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, upgradeConsNonlinear, NULL, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
17230  }
17231 
17232  /* add linear constraint handler parameters */
17233  SCIP_CALL( SCIPaddIntParam(scip,
17234  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17235  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17236  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17237  SCIP_CALL( SCIPaddIntParam(scip,
17238  "constraints/" CONSHDLR_NAME "/maxrounds",
17239  "maximal number of separation rounds per node (-1: unlimited)",
17240  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17241  SCIP_CALL( SCIPaddIntParam(scip,
17242  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17243  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17244  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17245  SCIP_CALL( SCIPaddIntParam(scip,
17246  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17247  "maximal number of cuts separated per separation round",
17248  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17249  SCIP_CALL( SCIPaddIntParam(scip,
17250  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17251  "maximal number of cuts separated per separation round in the root node",
17252  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17254  "constraints/" CONSHDLR_NAME "/presolpairwise",
17255  "should pairwise constraint comparison be performed in presolving?",
17256  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17258  "constraints/" CONSHDLR_NAME "/presolusehashing",
17259  "should hash table be used for detecting redundant constraints in advance",
17260  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17261  SCIP_CALL( SCIPaddIntParam(scip,
17262  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17263  "number for minimal pairwise presolve comparisons",
17264  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17266  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17267  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17268  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17270  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17271  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17272  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17274  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17275  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17276  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17278  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17279  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17280  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17282  "constraints/" CONSHDLR_NAME "/separateall",
17283  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17284  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17286  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17287  "should presolving search for aggregations in equations",
17288  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17290  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17291  "should presolving try to simplify inequalities",
17292  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17294  "constraints/" CONSHDLR_NAME "/dualpresolving",
17295  "should dual presolving steps be performed?",
17296  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17298  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17299  "should stuffing of singleton continuous variables be performed?",
17300  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17302  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17303  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17304  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17306  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17307  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17309  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17310  "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)?",
17311  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17313  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17314  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17315  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17317  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17318  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17319  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17321  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17322  "should presolving try to detect subsets of constraints parallel to the objective function?",
17323  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17325  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17326  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17327  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17329  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17330  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17331  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17332  SCIP_CALL( SCIPaddIntParam(scip,
17333  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17334  "maximum depth to apply ranged row propagation",
17335  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17336  SCIP_CALL( SCIPaddIntParam(scip,
17337  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17338  "frequency for applying ranged row propagation",
17339  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17341  "constraints/" CONSHDLR_NAME "/multaggrremove",
17342  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17343  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17344 
17345  return SCIP_OKAY;
17346 }
17347 
17348 /** includes a linear constraint update method into the linear constraint handler */
17350  SCIP* scip, /**< SCIP data structure */
17351  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17352  int priority, /**< priority of upgrading method */
17353  const char* conshdlrname /**< name of the constraint handler */
17354  )
17355 {
17356  SCIP_CONSHDLR* conshdlr;
17357  SCIP_CONSHDLRDATA* conshdlrdata;
17358  SCIP_LINCONSUPGRADE* linconsupgrade;
17359  char paramname[SCIP_MAXSTRLEN];
17360  char paramdesc[SCIP_MAXSTRLEN];
17361 
17362  assert(scip != NULL);
17363  assert(linconsupgd != NULL);
17364  assert(conshdlrname != NULL );
17365 
17366  /* find the linear constraint handler */
17367  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17368  if( conshdlr == NULL )
17369  {
17370  SCIPerrorMessage("linear constraint handler not found\n");
17371  return SCIP_PLUGINNOTFOUND;
17372  }
17373 
17374  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17375  assert(conshdlrdata != NULL);
17376 
17377  /* check if linear constraint update method already exists in constraint handler data */
17378  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17379  {
17380  /* create a linear constraint upgrade data object */
17381  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17382 
17383  /* insert linear constraint update method into constraint handler data */
17384  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17385 
17386  /* adds parameter to turn on and off the upgrading step */
17387  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17388  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17390  paramname, paramdesc,
17391  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17392  }
17393 
17394  return SCIP_OKAY;
17395 }
17396 
17397 /** creates and captures a linear constraint
17398  *
17399  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17400  */
17402  SCIP* scip, /**< SCIP data structure */
17403  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17404  const char* name, /**< name of constraint */
17405  int nvars, /**< number of nonzeros in the constraint */
17406  SCIP_VAR** vars, /**< array with variables of constraint entries */
17407  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17408  SCIP_Real lhs, /**< left hand side of constraint */
17409  SCIP_Real rhs, /**< right hand side of constraint */
17410  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17411  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17412  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17413  * Usually set to TRUE. */
17414  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17415  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17416  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17417  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17418  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17419  * Usually set to TRUE. */
17420  SCIP_Bool local, /**< is constraint only valid locally?
17421  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17422  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17423  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17424  * adds coefficients to this constraint. */
17425  SCIP_Bool dynamic, /**< is constraint subject to aging?
17426  * Usually set to FALSE. Set to TRUE for own cuts which
17427  * are separated as constraints. */
17428  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17429  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17430  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17431  * if it may be moved to a more global node?
17432  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17433  )
17434 {
17435  SCIP_CONSHDLR* conshdlr;
17436  SCIP_CONSDATA* consdata;
17437 
17438  assert(scip != NULL);
17439  assert(cons != NULL);
17440 
17441  /* find the linear constraint handler */
17442  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17443  if( conshdlr == NULL )
17444  {
17445  SCIPerrorMessage("linear constraint handler not found\n");
17446  return SCIP_PLUGINNOTFOUND;
17447  }
17448 
17449  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17450  * constraint after presolving we have to ensure that it holds active variables
17451  */
17452  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17453  {
17454  SCIP_VAR** consvars;
17455  SCIP_Real* consvals;
17456  SCIP_Real constant = 0.0;
17457  int nconsvars;
17458  int requiredsize;
17459 
17460  nconsvars = nvars;
17461  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17462  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17463 
17464  /* get active variables for new constraint */
17465  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17466 
17467  /* if space was not enough we need to resize the buffers */
17468  if( requiredsize > nconsvars )
17469  {
17470  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17471  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17472 
17473  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17474  assert(requiredsize <= nconsvars);
17475  }
17476 
17477  /* adjust sides and check that we do not subtract infinity values */
17478  if( SCIPisInfinity(scip, REALABS(constant)) )
17479  {
17480  if( constant < 0.0 )
17481  {
17482  if( SCIPisInfinity(scip, lhs) )
17483  {
17484  SCIPfreeBufferArray(scip, &consvals);
17485  SCIPfreeBufferArray(scip, &consvars);
17486 
17487  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);
17488 
17489  SCIPABORT();
17490  return SCIP_INVALIDDATA; /*lint !e527*/
17491  }
17492  if( SCIPisInfinity(scip, rhs) )
17493  {
17494  SCIPfreeBufferArray(scip, &consvals);
17495  SCIPfreeBufferArray(scip, &consvars);
17496 
17497  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);
17498 
17499  SCIPABORT();
17500  return SCIP_INVALIDDATA; /*lint !e527*/
17501  }
17502 
17503  lhs = -SCIPinfinity(scip);
17504  rhs = -SCIPinfinity(scip);
17505  }
17506  else
17507  {
17508  if( SCIPisInfinity(scip, -lhs) )
17509  {
17510  SCIPfreeBufferArray(scip, &consvals);
17511  SCIPfreeBufferArray(scip, &consvars);
17512 
17513  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);
17514 
17515  SCIPABORT();
17516  return SCIP_INVALIDDATA; /*lint !e527*/
17517  }
17518  if( SCIPisInfinity(scip, -rhs) )
17519  {
17520  SCIPfreeBufferArray(scip, &consvals);
17521  SCIPfreeBufferArray(scip, &consvars);
17522 
17523  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);
17524 
17525  SCIPABORT();
17526  return SCIP_INVALIDDATA; /*lint !e527*/
17527  }
17528 
17529  lhs = SCIPinfinity(scip);
17530  rhs = SCIPinfinity(scip);
17531  }
17532  }
17533  else
17534  {
17535  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17536  lhs -= constant;
17537  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17538  rhs -= constant;
17539 
17540  if( SCIPisInfinity(scip, -lhs) )
17541  lhs = -SCIPinfinity(scip);
17542  else if( SCIPisInfinity(scip, lhs) )
17543  lhs = SCIPinfinity(scip);
17544 
17545  if( SCIPisInfinity(scip, rhs) )
17546  rhs = SCIPinfinity(scip);
17547  else if( SCIPisInfinity(scip, -rhs) )
17548  rhs = -SCIPinfinity(scip);
17549  }
17550 
17551  /* create constraint data */
17552  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17553  assert(consdata != NULL);
17554 
17555  SCIPfreeBufferArray(scip, &consvals);
17556  SCIPfreeBufferArray(scip, &consvars);
17557  }
17558  else
17559  {
17560  /* create constraint data */
17561  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17562  assert(consdata != NULL);
17563  }
17564 
17565  /* create constraint */
17566  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17567  local, modifiable, dynamic, removable, stickingatnode) );
17568 
17569  return SCIP_OKAY;
17570 }
17571 
17572 /** creates and captures a linear constraint
17573  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17574  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17575  *
17576  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17577  *
17578  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17579  */
17581  SCIP* scip, /**< SCIP data structure */
17582  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17583  const char* name, /**< name of constraint */
17584  int nvars, /**< number of nonzeros in the constraint */
17585  SCIP_VAR** vars, /**< array with variables of constraint entries */
17586  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17587  SCIP_Real lhs, /**< left hand side of constraint */
17588  SCIP_Real rhs /**< right hand side of constraint */
17589  )
17590 {
17591  assert(scip != NULL);
17592 
17593  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17594  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17595 
17596  return SCIP_OKAY;
17598 
17599 /** creates by copying and captures a linear constraint */
17601  SCIP* scip, /**< target SCIP data structure */
17602  SCIP_CONS** cons, /**< pointer to store the created target constraint */
17603  SCIP* sourcescip, /**< source SCIP data structure */
17604  const char* name, /**< name of constraint */
17605  int nvars, /**< number of variables in source variable array */
17606  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17607  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17608  SCIP_Real lhs, /**< left hand side of the linear constraint */
17609  SCIP_Real rhs, /**< right hand side of the linear constraint */
17610  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17611  * variables of the target SCIP */
17612  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17613  * target constraints */
17614  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17615  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17616  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17617  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17618  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17619  SCIP_Bool local, /**< is constraint only valid locally? */
17620  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17621  SCIP_Bool dynamic, /**< is constraint subject to aging? */
17622  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17623  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17624  * if it may be moved to a more global node? */
17625  SCIP_Bool global, /**< create a global or a local copy? */
17626  SCIP_Bool* valid /**< pointer to store if the copying was valid */
17627  )
17628 {
17629  SCIP_VAR** vars;
17630  SCIP_Real* coefs;
17631 
17632  SCIP_Real constant;
17633  int requiredsize;
17634  int v;
17635  SCIP_Bool success;
17636 
17637  if( SCIPisGT(scip, lhs, rhs) )
17638  {
17639  *valid = FALSE;
17640  return SCIP_OKAY;
17641  }
17642 
17643  (*valid) = TRUE;
17644 
17645  if( nvars == 0 )
17646  {
17647  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17648  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17649  return SCIP_OKAY;
17650  }
17651 
17652  /* duplicate variable array */
17653  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17654 
17655  /* duplicate coefficient array */
17656  if( sourcecoefs != NULL )
17657  {
17658  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17659  }
17660  else
17661  {
17662  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
17663  for( v = 0; v < nvars; ++v )
17664  coefs[v] = 1.0;
17665  }
17666 
17667  constant = 0.0;
17668 
17669  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17670  * the target SCIP
17671  */
17672  if( !SCIPvarIsOriginal(vars[0]) )
17673  {
17674  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
17675 
17676  if( requiredsize > nvars )
17677  {
17678  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
17679  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
17680 
17681  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
17682  assert(requiredsize <= nvars);
17683  }
17684  }
17685  else
17686  {
17687  for( v = 0; v < nvars; ++v )
17688  {
17689  assert(SCIPvarIsOriginal(vars[v]));
17690  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
17691  assert(vars[v] != NULL);
17692  }
17693  }
17694 
17695 
17696  success = TRUE;
17697  /* map variables of the source constraint to variables of the target SCIP */
17698  for( v = 0; v < nvars && success; ++v )
17699  {
17700  SCIP_VAR* var;
17701  var = vars[v];
17702 
17703  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
17704  assert(!(success) || vars[v] != NULL);
17705  }
17706 
17707  /* only create the target constraint, if all variables could be copied */
17708  if( success )
17709  {
17710  if( !SCIPisInfinity(scip, -lhs) )
17711  lhs -= constant;
17712 
17713  if( !SCIPisInfinity(scip, rhs) )
17714  rhs -= constant;
17715 
17716  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17717  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17718  }
17719  else
17720  *valid = FALSE;
17721 
17722  /* free buffer array */
17723  SCIPfreeBufferArray(scip, &coefs);
17724  SCIPfreeBufferArray(scip, &vars);
17725 
17726  return SCIP_OKAY;
17727 }
17728 
17729 /** adds coefficient to linear constraint (if it is not zero) */
17731  SCIP* scip, /**< SCIP data structure */
17732  SCIP_CONS* cons, /**< constraint data */
17733  SCIP_VAR* var, /**< variable of constraint entry */
17734  SCIP_Real val /**< coefficient of constraint entry */
17735  )
17736 {
17737  assert(scip != NULL);
17738  assert(cons != NULL);
17739  assert(var != NULL);
17740 
17741  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17742  {
17743  SCIPerrorMessage("constraint is not linear\n");
17744  return SCIP_INVALIDDATA;
17745  }
17746 
17747  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17748  * constraint after presolving we have to ensure that it holds active variables
17749  */
17750  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
17751  {
17752  SCIP_CONSDATA* consdata;
17753  SCIP_VAR** consvars;
17754  SCIP_Real* consvals;
17755  SCIP_Real constant = 0.0;
17756  SCIP_Real rhs;
17757  SCIP_Real lhs;
17758  int nconsvars;
17759  int requiredsize;
17760  int v;
17761 
17762  nconsvars = 1;
17763  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
17764  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
17765  consvars[0] = var;
17766  consvals[0] = val;
17767 
17768  /* get active variables for new constraint */
17769  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17770 
17771  /* if space was not enough we need to resize the buffers */
17772  if( requiredsize > nconsvars )
17773  {
17774  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17775  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17776 
17777  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17778  assert(requiredsize <= nconsvars);
17779  }
17780 
17781  consdata = SCIPconsGetData(cons);
17782  assert(consdata != NULL);
17783 
17784  lhs = consdata->lhs;
17785  rhs = consdata->rhs;
17786 
17787  /* adjust sides and check that we do not subtract infinity values */
17788  /* constant is infinite */
17789  if( SCIPisInfinity(scip, REALABS(constant)) )
17790  {
17791  if( constant < 0.0 )
17792  {
17793  if( SCIPisInfinity(scip, lhs) )
17794  {
17795  SCIPfreeBufferArray(scip, &consvals);
17796  SCIPfreeBufferArray(scip, &consvars);
17797 
17798  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));
17799 
17800  SCIPABORT();
17801  return SCIP_INVALIDDATA; /*lint !e527*/
17802  }
17803  if( SCIPisInfinity(scip, rhs) )
17804  {
17805  SCIPfreeBufferArray(scip, &consvals);
17806  SCIPfreeBufferArray(scip, &consvars);
17807 
17808  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));
17809 
17810  SCIPABORT();
17811  return SCIP_INVALIDDATA; /*lint !e527*/
17812  }
17813 
17814  lhs = -SCIPinfinity(scip);
17815  rhs = -SCIPinfinity(scip);
17816  }
17817  else
17818  {
17819  if( SCIPisInfinity(scip, -lhs) )
17820  {
17821  SCIPfreeBufferArray(scip, &consvals);
17822  SCIPfreeBufferArray(scip, &consvars);
17823 
17824  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));
17825 
17826  SCIPABORT();
17827  return SCIP_INVALIDDATA; /*lint !e527*/
17828  }
17829  if( SCIPisInfinity(scip, -rhs) )
17830  {
17831  SCIPfreeBufferArray(scip, &consvals);
17832  SCIPfreeBufferArray(scip, &consvars);
17833 
17834  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));
17835 
17836  SCIPABORT();
17837  return SCIP_INVALIDDATA; /*lint !e527*/
17838  }
17839 
17840  lhs = SCIPinfinity(scip);
17841  rhs = SCIPinfinity(scip);
17842  }
17843  }
17844  /* constant is not infinite */
17845  else
17846  {
17847  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17848  lhs -= constant;
17849  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17850  rhs -= constant;
17851 
17852  if( SCIPisInfinity(scip, -lhs) )
17853  lhs = -SCIPinfinity(scip);
17854  else if( SCIPisInfinity(scip, lhs) )
17855  lhs = SCIPinfinity(scip);
17856 
17857  if( SCIPisInfinity(scip, rhs) )
17858  rhs = SCIPinfinity(scip);
17859  else if( SCIPisInfinity(scip, -rhs) )
17860  rhs = -SCIPinfinity(scip);
17861  }
17862 
17863  /* add all active variables to constraint */
17864  for( v = nconsvars - 1; v >= 0; --v )
17865  {
17866  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
17867  }
17868 
17869  /* update left and right hand sides */
17870  SCIP_CALL( chgLhs(scip, cons, lhs));
17871  SCIP_CALL( chgRhs(scip, cons, rhs));
17872 
17873  SCIPfreeBufferArray(scip, &consvals);
17874  SCIPfreeBufferArray(scip, &consvars);
17875  }
17876  else
17877  {
17878  SCIP_CALL( addCoef(scip, cons, var, val) );
17879  }
17880 
17881  return SCIP_OKAY;
17882 }
17883 
17884 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
17885  * not yet contained in the constraint
17886  *
17887  * @note This method may only be called during problem creation stage for an original constraint and variable.
17888  *
17889  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17890  */
17892  SCIP* scip, /**< SCIP data structure */
17893  SCIP_CONS* cons, /**< constraint data */
17894  SCIP_VAR* var, /**< variable of constraint entry */
17895  SCIP_Real val /**< new coefficient of constraint entry */
17896  )
17897 {
17898  SCIP_CONSDATA* consdata;
17899  SCIP_VAR** vars;
17900  SCIP_Bool found;
17901  int i;
17902 
17903  assert(scip != NULL);
17904  assert(cons != NULL);
17905  assert(var != NULL);
17906 
17907  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17908  {
17909  SCIPerrorMessage("constraint is not linear\n");
17910  return SCIP_INVALIDDATA;
17911  }
17912 
17913  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
17914  {
17915  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
17916  return SCIP_INVALIDDATA;
17917  }
17918 
17919  consdata = SCIPconsGetData(cons);
17920  assert(consdata != NULL);
17921 
17922  vars = consdata->vars;
17923  found = FALSE;
17924  i = 0;
17925  while( i < consdata->nvars )
17926  {
17927  if( vars[i] == var )
17928  {
17929  if( found || SCIPisZero(scip, val) )
17930  {
17931  SCIP_CALL( delCoefPos(scip, cons, i) );
17932 
17933  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
17934  i--;
17935  }
17936  else
17937  {
17938  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
17939  }
17940  found = TRUE;
17941  }
17942  i++;
17943  }
17944 
17945  if( !found && !SCIPisZero(scip, val) )
17946  {
17947  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
17948  }
17949 
17950  return SCIP_OKAY;
17951 }
17952 
17953 /** deletes variable from linear constraint
17954  *
17955  * @note This method may only be called during problem creation stage for an original constraint and variable.
17956  *
17957  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17958  */
17960  SCIP* scip, /**< SCIP data structure */
17961  SCIP_CONS* cons, /**< constraint data */
17962  SCIP_VAR* var /**< variable of constraint entry */
17963  )
17964 {
17965  assert(scip != NULL);
17966  assert(cons != NULL);
17967  assert(var != NULL);
17968 
17969  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
17970 
17971  return SCIP_OKAY;
17972 }
17973 
17974 /** gets left hand side of linear constraint */
17976  SCIP* scip, /**< SCIP data structure */
17977  SCIP_CONS* cons /**< constraint data */
17978  )
17979 {
17980  SCIP_CONSDATA* consdata;
17981 
17982  assert(cons != NULL);
17983 
17984  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17985  {
17986  SCIPerrorMessage("constraint is not linear\n");
17987  SCIPABORT();
17988  return SCIP_INVALID; /*lint !e527*/
17989  }
17990 
17991  consdata = SCIPconsGetData(cons);
17992  assert(consdata != NULL);
17993 
17994  return consdata->lhs;
17995 }
17996 
17997 /** gets right hand side of linear constraint */
17999  SCIP* scip, /**< SCIP data structure */
18000  SCIP_CONS* cons /**< constraint data */
18001  )
18002 {
18003  SCIP_CONSDATA* consdata;
18004 
18005  assert(cons != NULL);
18006 
18007  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18008  {
18009  SCIPerrorMessage("constraint is not linear\n");
18010  SCIPABORT();
18011  return SCIP_INVALID; /*lint !e527*/
18012  }
18013 
18014  consdata = SCIPconsGetData(cons);
18015  assert(consdata != NULL);
18016 
18017  return consdata->rhs;
18018 }
18019 
18020 /** changes left hand side of linear constraint */
18022  SCIP* scip, /**< SCIP data structure */
18023  SCIP_CONS* cons, /**< constraint data */
18024  SCIP_Real lhs /**< new left hand side */
18025  )
18026 {
18027  assert(scip != NULL);
18028  assert(cons != NULL);
18029 
18030  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18031  {
18032  SCIPerrorMessage("constraint is not linear\n");
18033  return SCIP_INVALIDDATA;
18034  }
18035 
18036  SCIP_CALL( chgLhs(scip, cons, lhs) );
18037 
18038  return SCIP_OKAY;
18039 }
18040 
18041 /** changes right hand side of linear constraint */
18043  SCIP* scip, /**< SCIP data structure */
18044  SCIP_CONS* cons, /**< constraint data */
18045  SCIP_Real rhs /**< new right hand side */
18046  )
18047 {
18048  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18049  {
18050  SCIPerrorMessage("constraint is not linear\n");
18051  return SCIP_INVALIDDATA;
18052  }
18053 
18054  SCIP_CALL( chgRhs(scip, cons, rhs) );
18055 
18056  return SCIP_OKAY;
18057 }
18058 
18059 /** gets the number of variables in the linear constraint */
18060 int SCIPgetNVarsLinear(
18061  SCIP* scip, /**< SCIP data structure */
18062  SCIP_CONS* cons /**< constraint data */
18063  )
18064 {
18065  SCIP_CONSDATA* consdata;
18066 
18067  assert(cons != NULL);
18068 
18069  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18070  {
18071  SCIPerrorMessage("constraint is not linear\n");
18072  SCIPABORT();
18073  return -1; /*lint !e527*/
18074  }
18075 
18076  consdata = SCIPconsGetData(cons);
18077  assert(consdata != NULL);
18078 
18079  return consdata->nvars;
18080 }
18081 
18082 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18084  SCIP* scip, /**< SCIP data structure */
18085  SCIP_CONS* cons /**< constraint data */
18086  )
18087 {
18088  SCIP_CONSDATA* consdata;
18089 
18090  assert(cons != NULL);
18091 
18092  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18093  {
18094  SCIPerrorMessage("constraint is not linear\n");
18095  SCIPABORT();
18096  return NULL; /*lint !e527*/
18097  }
18098 
18099  consdata = SCIPconsGetData(cons);
18100  assert(consdata != NULL);
18101 
18102  return consdata->vars;
18103 }
18104 
18105 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18107  SCIP* scip, /**< SCIP data structure */
18108  SCIP_CONS* cons /**< constraint data */
18109  )
18110 {
18111  SCIP_CONSDATA* consdata;
18112 
18113  assert(cons != NULL);
18114 
18115  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18116  {
18117  SCIPerrorMessage("constraint is not linear\n");
18118  SCIPABORT();
18119  return NULL; /*lint !e527*/
18120  }
18121 
18122  consdata = SCIPconsGetData(cons);
18123  assert(consdata != NULL);
18124 
18125  return consdata->vals;
18126 }
18127 
18128 /** gets the activity of the linear constraint in the given solution
18129  *
18130  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18131  * comprises positive and negative infinity contributions
18132  */
18134  SCIP* scip, /**< SCIP data structure */
18135  SCIP_CONS* cons, /**< constraint data */
18136  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18137  )
18138 {
18139  SCIP_CONSDATA* consdata;
18140 
18141  assert(cons != NULL);
18142 
18143  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18144  {
18145  SCIPerrorMessage("constraint is not linear\n");
18146  SCIPABORT();
18147  return SCIP_INVALID; /*lint !e527*/
18148  }
18149 
18150  consdata = SCIPconsGetData(cons);
18151  assert(consdata != NULL);
18152 
18153  if( consdata->row != NULL )
18154  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18155  else
18156  return consdataGetActivity(scip, consdata, sol);
18157 }
18158 
18159 /** gets the feasibility of the linear constraint in the given solution */
18161  SCIP* scip, /**< SCIP data structure */
18162  SCIP_CONS* cons, /**< constraint data */
18163  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18164  )
18165 {
18166  SCIP_CONSDATA* consdata;
18167 
18168  assert(cons != NULL);
18169 
18170  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18171  {
18172  SCIPerrorMessage("constraint is not linear\n");
18173  SCIPABORT();
18174  return SCIP_INVALID; /*lint !e527*/
18175  }
18176 
18177  consdata = SCIPconsGetData(cons);
18178  assert(consdata != NULL);
18179 
18180  if( consdata->row != NULL )
18181  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18182  else
18183  return consdataGetFeasibility(scip, consdata, sol);
18184 }
18185 
18186 /** gets the dual solution of the linear constraint in the current LP */
18188  SCIP* scip, /**< SCIP data structure */
18189  SCIP_CONS* cons /**< constraint data */
18190  )
18191 {
18192  SCIP_CONSDATA* consdata;
18193 
18194  assert(cons != NULL);
18195  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18196 
18197  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18198  {
18199  SCIPerrorMessage("constraint is not linear\n");
18200  SCIPABORT();
18201  return SCIP_INVALID; /*lint !e527*/
18202  }
18203 
18204  consdata = SCIPconsGetData(cons);
18205  assert(consdata != NULL);
18206 
18207  if( consdata->row != NULL )
18208  return SCIProwGetDualsol(consdata->row);
18209  else
18210  return 0.0;
18211 }
18212 
18213 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18215  SCIP* scip, /**< SCIP data structure */
18216  SCIP_CONS* cons /**< constraint data */
18217  )
18218 {
18219  SCIP_CONSDATA* consdata;
18220 
18221  assert(cons != NULL);
18222  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18223 
18224  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18225  {
18226  SCIPerrorMessage("constraint is not linear\n");
18227  SCIPABORT();
18228  return SCIP_INVALID; /*lint !e527*/
18229  }
18230 
18231  consdata = SCIPconsGetData(cons);
18232  assert(consdata != NULL);
18233 
18234  if( consdata->row != NULL )
18235  return SCIProwGetDualfarkas(consdata->row);
18236  else
18237  return 0.0;
18238 }
18239 
18240 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18241  * the user must not modify the row!
18242  */
18244  SCIP* scip, /**< SCIP data structure */
18245  SCIP_CONS* cons /**< constraint data */
18246  )
18247 {
18248  SCIP_CONSDATA* consdata;
18249 
18250  assert(cons != NULL);
18251 
18252  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18253  {
18254  SCIPerrorMessage("constraint is not linear\n");
18255  SCIPABORT();
18256  return NULL; /*lint !e527*/
18257  }
18258 
18259  consdata = SCIPconsGetData(cons);
18260  assert(consdata != NULL);
18261 
18262  return consdata->row;
18263 }
18264 
18265 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18267  SCIP* scip, /**< SCIP data structure */
18268  SCIP_CONS* cons, /**< source constraint to try to convert */
18269  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18270  )
18271 {
18272  SCIP_CONSHDLR* conshdlr;
18273  SCIP_CONSHDLRDATA* conshdlrdata;
18274  SCIP_CONSDATA* consdata;
18275  SCIP_VAR* var;
18276  SCIP_Real val;
18277  SCIP_Real lb;
18278  SCIP_Real ub;
18279  SCIP_Real poscoeffsum;
18280  SCIP_Real negcoeffsum;
18281  SCIP_Bool integral;
18282  int nposbin;
18283  int nnegbin;
18284  int nposint;
18285  int nnegint;
18286  int nposimpl;
18287  int nnegimpl;
18288  int nposimplbin;
18289  int nnegimplbin;
18290  int nposcont;
18291  int nnegcont;
18292  int ncoeffspone;
18293  int ncoeffsnone;
18294  int ncoeffspint;
18295  int ncoeffsnint;
18296  int ncoeffspfrac;
18297  int ncoeffsnfrac;
18298  int i;
18299 
18300  assert(scip != NULL);
18301  assert(cons != NULL);
18302  assert(upgdcons != NULL);
18303 
18304  *upgdcons = NULL;
18305 
18306  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18307  if( SCIPconsIsModifiable(cons) )
18308  return SCIP_OKAY;
18309 
18310  /* check for upgradability */
18311  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18312  return SCIP_OKAY;
18313 
18314  /* get the constraint handler and check, if it's really a linear constraint */
18315  conshdlr = SCIPconsGetHdlr(cons);
18316  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18317  {
18318  SCIPerrorMessage("constraint is not linear\n");
18319  return SCIP_INVALIDDATA;
18320  }
18321 
18322  /* get constraint handler data and constraint data */
18323  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18324  assert(conshdlrdata != NULL);
18325  consdata = SCIPconsGetData(cons);
18326  assert(consdata != NULL);
18327 
18328  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18329  if( consdata->upgraded )
18330  return SCIP_OKAY;
18331 
18332  /* check, if the constraint is already stored as LP row */
18333  if( consdata->row != NULL )
18334  {
18335  if( SCIProwIsInLP(consdata->row) )
18336  {
18337  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18338  return SCIP_INVALIDDATA;
18339  }
18340  else
18341  {
18342  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18343  }
18344  }
18345 
18346  /* normalize constraint */
18347  SCIP_CALL( normalizeCons(scip, cons) );
18348 
18349 
18350  /*
18351  * calculate some statistics on linear constraint
18352  */
18353 
18354  nposbin = 0;
18355  nnegbin = 0;
18356  nposint = 0;
18357  nnegint = 0;
18358  nposimpl = 0;
18359  nnegimpl = 0;
18360  nposimplbin = 0;
18361  nnegimplbin = 0;
18362  nposcont = 0;
18363  nnegcont = 0;
18364  ncoeffspone = 0;
18365  ncoeffsnone = 0;
18366  ncoeffspint = 0;
18367  ncoeffsnint = 0;
18368  ncoeffspfrac = 0;
18369  ncoeffsnfrac = 0;
18370  integral = TRUE;
18371  poscoeffsum = 0.0;
18372  negcoeffsum = 0.0;
18373 
18374  for( i = 0; i < consdata->nvars; ++i )
18375  {
18376  var = consdata->vars[i];
18377  val = consdata->vals[i];
18378  lb = SCIPvarGetLbLocal(var);
18379  ub = SCIPvarGetUbLocal(var);
18380  assert(!SCIPisZero(scip, val));
18381 
18382  switch( SCIPvarGetType(var) )
18383  {
18384  case SCIP_VARTYPE_BINARY:
18385  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18386  integral = integral && SCIPisIntegral(scip, val);
18387  if( val >= 0.0 )
18388  nposbin++;
18389  else
18390  nnegbin++;
18391  break;
18392  case SCIP_VARTYPE_INTEGER:
18393  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18394  integral = integral && SCIPisIntegral(scip, val);
18395  if( val >= 0.0 )
18396  nposint++;
18397  else
18398  nnegint++;
18399  break;
18400  case SCIP_VARTYPE_IMPLINT:
18401  if( SCIPvarIsBinary(var) )
18402  {
18403  if( val >= 0.0 )
18404  nposimplbin++;
18405  else
18406  nnegimplbin++;
18407  }
18408  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18409  integral = integral && SCIPisIntegral(scip, val);
18410  if( val >= 0.0 )
18411  nposimpl++;
18412  else
18413  nnegimpl++;
18414  break;
18416  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18417  if( val >= 0.0 )
18418  nposcont++;
18419  else
18420  nnegcont++;
18421  break;
18422  default:
18423  SCIPerrorMessage("unknown variable type\n");
18424  return SCIP_INVALIDDATA;
18425  }
18426  if( SCIPisEQ(scip, val, 1.0) )
18427  ncoeffspone++;
18428  else if( SCIPisEQ(scip, val, -1.0) )
18429  ncoeffsnone++;
18430  else if( SCIPisIntegral(scip, val) )
18431  {
18432  if( SCIPisPositive(scip, val) )
18433  ncoeffspint++;
18434  else
18435  ncoeffsnint++;
18436  }
18437  else
18438  {
18439  if( SCIPisPositive(scip, val) )
18440  ncoeffspfrac++;
18441  else
18442  ncoeffsnfrac++;
18443  }
18444  if( SCIPisPositive(scip, val) )
18445  poscoeffsum += val;
18446  else
18447  negcoeffsum += val;
18448  }
18449 
18450 
18451  /*
18452  * call the upgrading methods
18453  */
18454 
18455  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18456  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18457  SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
18458  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18459  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18460  poscoeffsum, negcoeffsum, integral);
18461 
18462  /* try all upgrading methods in priority order in case the upgrading step is enable */
18463  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18464  {
18465  if( conshdlrdata->linconsupgrades[i]->active )
18466  {
18467  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18468  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18469  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18470  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18471  poscoeffsum, negcoeffsum, integral,
18472  upgdcons) );
18473  }
18474  }
18475 
18476 #ifdef SCIP_DEBUG
18477  if( *upgdcons != NULL )
18478  {
18479  SCIPdebugPrintCons(scip, cons, NULL);
18480  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18481  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18482  }
18483 #endif
18484 
18485  return SCIP_OKAY;
18486 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define EVENTHDLR_DESC
Definition: cons_linear.c:80
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:72
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:104
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47363
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28372
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:22593
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19211
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:75
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:41459
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6671
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1401
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
Definition: cons_linear.c:825
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:378
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:691
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3930
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22523
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3112
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19649
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:103
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:91
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17068
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47311
#define CONSHDLR_NAME
Definition: cons_linear.c:61
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19509
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:71
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
#define BINWEIGHT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3133
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2265
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_Real val, SCIP_BOUNDTYPE boundtype, SCIP_Bool global, SCIP_Bool checkreliability)
Definition: cons_linear.c:1568
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:138
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1506
#define MAXSCALEDCOEF
Definition: cons_linear.c:145
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:100
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:43453
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7684
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17878
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:47661
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:87
#define DEFAULT_SORTVARS
Definition: cons_linear.c:97
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9295
static SCIP_RETCODE tightenVarLb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5311
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
static SCIP_RETCODE findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
Definition: scip.c:43481
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16863
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
Definition: scip.c:46683
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:794
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:7886
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:46813
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17056
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip.c:27959
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47088
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47739
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2026
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: scip.c:47846
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip.c:6406
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2256
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:481
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:89
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:28112
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1269
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:132
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:3005
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47350
static void consdataGetGlbActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *glbminactivity, SCIP_Real *glbmaxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2830
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3191
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:115
#define FALSE
Definition: def.h:64
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip.c:21985
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1170
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7996
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5894
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47100
static void consdataGetGlbActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2892
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:562
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:109
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28630
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip.c:13408
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17113
enum Proprule PROPRULE
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:93
#define SCIPstatisticMessage
Definition: pub_message.h:104
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27251
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
Definition: cons_linear.c:7447
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:7855
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17022
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
static GRAPHNODE ** active
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22639
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides)
Definition: cons_linear.c:8785
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:94
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5948
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9126
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8345
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1235
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip.c:12908
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
enum Proprule PROPRULE
Definition: cons_linear.c:328
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
static SCIP_DECL_CONSRESPROP(consRespropLinear)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:387
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5698
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:21953
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16873
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
Definition: scip.c:6688
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:37034
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:728
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip.c:6475
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1501
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17102
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3178
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16504
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
#define SCIPdebugMsgPrint
Definition: scip.h:456
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4265
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2272
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:112
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8047
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:90
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:11992
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:4980
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:46415
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip.c:18214
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:76
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27184
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47435
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:77
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:9455
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2014
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47423
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8285
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:66
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17092
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16695
#define MAXCONSPRESOLROUNDS
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27133
static SCIP_DECL_EVENTEXEC(eventExecLinear)
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8721
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:47646
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:502
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip.c:27884
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:25479
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5189
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
Definition: cons_linear.c:7110
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24222
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:82
static SCIP_RETCODE aggregateConstraints(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *commonidx0, int *commonidx1, int *diffidx0minus1, int *diffidx1minus0, int nvarscommon, int commonidxweight, int diffidx0minus1weight, int diffidx1minus0weight, SCIP_Real maxaggrnormscale, int *nchgcoefs, SCIP_Bool *aggregated)
SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip.c:25818
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:122
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1162
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip.c:1054
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8325
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:84
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5242
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2453
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:475
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47765
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:67
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:13216
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25868
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13297
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax)
Definition: cons_linear.c:2552
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22750
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:19311
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1377
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24094
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:489
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:140
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3533
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:421
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2099
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3264
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2049
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:369
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:8868
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17033
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
constraint handler for quadratic constraints
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5045
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28602
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3809
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_linear.c:5096
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:406
#define REALABS(x)
Definition: def.h:173
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip.c:4451
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:592
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:73
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8335
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5009
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5213
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47337
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:65
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5380
#define SCIPhashSignature64(a)
Definition: pub_misc.h:472
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip.c:19255
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17080
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2395
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13802
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47324
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
Definition: cons_linear.c:2352
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:3997
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:262
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
static SCIP_DECL_CONSTRANS(consTransLinear)
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:29208
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4515
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7537
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
Definition: scip.c:47051
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2156
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:127
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21853
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1059
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16791
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2522
#define QUADCONSUPGD_PRIORITY
Definition: cons_linear.c:156
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3412
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47236
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:30585
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:74
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:68
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4081
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1350
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30402
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3044
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6939
constraint handler for nonlinear constraints
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:540
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:119
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:117
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4486
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7394
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11353
methods for debugging
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8115
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2297
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:30561
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2003
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1216
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17868
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2290
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:157
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17011
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17619
static int getVarWeight(SCIP_VAR *var)
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25575
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:42050
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16517
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21714
#define MAXDNOM
Definition: cons_linear.c:144
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip.c:12040
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
Definition: scip.c:43019
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2326
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17044
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47791
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:31111
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:88
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12184
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22819
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
Proprule
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:86
#define SCIP_MAXTREEDEPTH
Definition: def.h:286
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35836
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:116
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7370
#define MINVALRECOMP
Definition: cons_linear.c:153
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:63
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8377
#define SCIP_REAL_MAX
Definition: def.h:150
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2598
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1296
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip.c:17848
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip.c:13519
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:146
static SCIP_DECL_CONSCHECK(consCheckLinear)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:6229
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:516
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3158
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSPARSE(consParseLinear)
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5640
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:624
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5081
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2679
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47112
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
static const SCIP_Real scalars[]
Definition: lp.c:5618
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1920
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11492
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22932
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:6109
#define CONTWEIGHT
SCIP_Real SCIPgetHugeValue(SCIP *scip)
Definition: scip.c:47065
static SCIP_DECL_CONSLOCK(consLockLinear)
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip.c:27909
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1430
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:762
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip.c:6133
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:12862
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:7819
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip.c:1870
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:25885
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:712
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1138
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47375
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9351
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:83
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25684
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4140
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6943
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:30694
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:59
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9409
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:118
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
#define EVENTHDLR_NAME
Definition: cons_linear.c:79
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
Definition: scip.c:47124
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:64
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4557
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1098
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:25848
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define SCIP_INVALID
Definition: def.h:169
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:135
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:31160
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3655
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:62
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
Definition: scip.c:46499
#define SCIP_Longint
Definition: def.h:134
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17388
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:31134
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:446
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:261
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7752
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1323
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9465
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:22605
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16804
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:360
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8195
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define MAXVALRECOMP
Definition: cons_linear.c:152
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:657
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:106
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:13049
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47161
static SCIP_DECL_CONSEXIT(consExitLinear)
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:137
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6181
#define SCIPcombineTwoInt(a, b)
Definition: pub_misc.h:479
#define SCIPABORT()
Definition: def.h:322
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17735
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8448
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16883
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:347
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip.c:11092
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define INTWEIGHT
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4798
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8700
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47149
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:57
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1953
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
int SCIPgetNSepaRounds(SCIP *scip)
Definition: scip.c:42884
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:92
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16817
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1978
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1024
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip.c:27859
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:107
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:136
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)