Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Michael Winkler
23  * @author Gerald Gamrath
24  * @author Domenico Salvagnin
25  *
26  * Linear constraints are separated with a high priority, because they are easy
27  * to separate. Instead of using the global cut pool, the same effect can be
28  * implemented by adding linear constraints to the root node, such that they are
29  * separated each time, the linear constraints are separated. A constraint
30  * handler, which generates linear constraints in this way should have a lower
31  * separation priority than the linear constraint handler, and it should have a
32  * separation frequency that is a multiple of the frequency of the linear
33  * constraint handler. In this way, it can be avoided to separate the same cut
34  * twice, because if a separation run of the handler is always preceded by a
35  * separation of the linear constraints, the priorily added constraints are
36  * always satisfied.
37  *
38  * Linear constraints are enforced and checked with a very low priority. Checking
39  * of (many) linear constraints is much more involved than checking the solution
40  * values for integrality. Because we are separating the linear constraints quite
41  * often, it is only necessary to enforce them for integral solutions. A constraint
42  * handler which generates pool cuts in its enforcing method should have an
43  * enforcing priority smaller than that of the linear constraint handler to avoid
44  * regenerating constraints which already exist.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include <assert.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <ctype.h>
53 
54 #include "scip/cons_linear.h"
55 #include "scip/cons_knapsack.h"
56 #include "scip/cons_quadratic.h"
57 #include "scip/cons_nonlinear.h"
58 #include "scip/pub_misc.h"
59 #include "scip/debug.h"
60 
61 #define CONSHDLR_NAME "linear"
62 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
63 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
64 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
65 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
66 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
67 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
68 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
69  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
70 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
71 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
72 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
73 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
74 
75 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
76 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
77 
78 #define EVENTHDLR_NAME "linear"
79 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
80 
81 #define CONFLICTHDLR_NAME "linear"
82 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
83 #define CONFLICTHDLR_PRIORITY -1000000
84 
85 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
86 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
87 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
88 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
89 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
90 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
91 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
92 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
93 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
94  * comparison round */
95 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
96  * propagation? */
97 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
98  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
99 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
100  * (0.0: disable constraint aggregation) */
101 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
102  * (faster, but numerically less stable) */
103 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
104  * to best node's dual bound for separating knapsack cardinality cuts */
105 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
106  * the ones with non-zero dual value? */
107 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
108 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
109 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
110 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
111 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
112  * constraints using the cheapest variable? */
113 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
114  * function defining an upper bound and prevent these constraints from
115  * entering the LP */
116 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
117  * function defining a lower bound and prevent these constraints from
118  * entering the LP */
119 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
120  * objective function */
121 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
122 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
123 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
124 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
125 
126 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
127  * removed afterwards? */
128 
129 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
130 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
131 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
132  * type
133  */
134 
135 #define 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  consdata->glbminactivity += consdata->vals[i] * bound;
1321  }
1322 
1323  /* the activity was just computed from scratch and is valid now */
1324  consdata->validglbminact = TRUE;
1325 
1326  /* the activity was just computed from scratch, mark it to be reliable */
1327  consdata->lastglbminactivity = consdata->glbminactivity;
1328 }
1329 
1330 /** recompute the global maxactivity of a constraint */
1331 static
1333  SCIP* scip, /**< SCIP data structure */
1334  SCIP_CONSDATA* consdata /**< linear constraint data */
1335  )
1336 {
1337  int i;
1338  SCIP_Real bound;
1339 
1340  consdata->glbmaxactivity = 0;
1341 
1342  for( i = consdata->nvars - 1; i >= 0; --i )
1343  {
1344  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1345  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1346  consdata->glbmaxactivity += consdata->vals[i] * bound;
1347  }
1348 
1349  /* the activity was just computed from scratch and is valid now */
1350  consdata->validglbmaxact = TRUE;
1351 
1352  /* the activity was just computed from scratch, mark it to be reliable */
1353  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1354 }
1355 
1356 /** calculates maximum absolute value of coefficients */
1357 static
1359  SCIP_CONSDATA* consdata /**< linear constraint data */
1360  )
1361 {
1362  SCIP_Real absval;
1363  int i;
1364 
1365  assert(consdata != NULL);
1366  assert(!consdata->validmaxabsval);
1367  assert(consdata->maxabsval >= SCIP_INVALID);
1368 
1369  consdata->validmaxabsval = TRUE;
1370  consdata->maxabsval = 0.0;
1371  for( i = 0; i < consdata->nvars; ++i )
1372  {
1373  absval = consdata->vals[i];
1374  absval = REALABS(absval);
1375  if( absval > consdata->maxabsval )
1376  consdata->maxabsval = absval;
1377  }
1378 }
1379 
1380 /** calculates minimum absolute value of coefficients */
1381 static
1383  SCIP_CONSDATA* consdata /**< linear constraint data */
1384  )
1385 {
1386  SCIP_Real absval;
1387  int i;
1388 
1389  assert(consdata != NULL);
1390  assert(!consdata->validminabsval);
1391  assert(consdata->minabsval >= SCIP_INVALID);
1392 
1393  consdata->validminabsval = TRUE;
1394 
1395  if( consdata->nvars > 0 )
1396  consdata->minabsval = REALABS(consdata->vals[0]);
1397  else
1398  consdata->minabsval = 0.0;
1400  for( i = 1; i < consdata->nvars; ++i )
1401  {
1402  absval = consdata->vals[i];
1403  absval = REALABS(absval);
1404  if( absval < consdata->minabsval )
1405  consdata->minabsval = absval;
1406  }
1407 }
1408 
1409 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1410 static
1412  SCIP_CONSDATA* consdata /**< linear constraint data */
1413  )
1414 {
1415  int v;
1416 
1417  assert(!consdata->hasnonbinvalid);
1418  consdata->hasnonbinvar = FALSE;
1419  consdata->hascontvar = FALSE;
1420 
1421  for( v = consdata->nvars - 1; v >= 0; --v )
1422  {
1423  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1424 
1425  if( vartype != SCIP_VARTYPE_BINARY )
1426  {
1427  consdata->hasnonbinvar = TRUE;
1429  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1430  {
1431  consdata->hascontvar = TRUE;
1432  break;
1433  }
1434  }
1435  }
1436  assert(consdata->hascontvar || v < 0);
1437 
1438  consdata->hasnonbinvalid = TRUE;
1439 }
1440 
1441 
1442 #ifdef CHECKMAXACTDELTA
1443 /* checks that the stored maximal activity delta (if not invalid) is correct */
1444 static
1446  SCIP* scip, /**< SCIP data structure */
1447  SCIP_CONSDATA* consdata /**< linear constraint data */
1448  )
1449 {
1450  if( consdata->maxactdelta != SCIP_INVALID )
1451  {
1452  SCIP_Real maxactdelta = 0.0;
1453  SCIP_Real domain;
1454  SCIP_Real delta;
1455  SCIP_Real lb;
1456  SCIP_Real ub;
1457  int v;
1458 
1459  for( v = consdata->nvars - 1; v >= 0; --v )
1460  {
1461  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1462  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1463 
1464  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1465  {
1466  maxactdelta = SCIPinfinity(scip);
1467  break;
1468  }
1469 
1470  domain = ub - lb;
1471  delta = REALABS(consdata->vals[v]) * domain;
1472 
1473  if( delta > maxactdelta )
1474  {
1475  maxactdelta = delta;
1476  }
1477  }
1478  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1479  }
1480 }
1481 #else
1482 #define checkMaxActivityDelta(scip, consdata) /**/
1483 #endif
1484 
1485 /** recompute maximal activity contribution for a single variable */
1486 static
1488  SCIP* scip, /**< SCIP data structure */
1489  SCIP_CONSDATA* consdata /**< linear constraint data */
1490  )
1491 {
1492  SCIP_Real delta;
1493  int v;
1494 
1495  consdata->maxactdelta = 0.0;
1496 
1497  if( !consdata->hasnonbinvalid )
1498  consdataCheckNonbinvar(consdata);
1500  /* easy case, the problem consists only of binary variables */
1501  if( !consdata->hasnonbinvar )
1502  {
1503  for( v = consdata->nvars - 1; v >= 0; --v )
1504  {
1505  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1506  {
1507  delta = REALABS(consdata->vals[v]);
1508 
1509  if( delta > consdata->maxactdelta )
1510  {
1511  consdata->maxactdelta = delta;
1512  consdata->maxactdeltavar = consdata->vars[v];
1513  }
1514  }
1515  }
1516  return;
1517  }
1518 
1519  for( v = consdata->nvars - 1; v >= 0; --v )
1520  {
1521  SCIP_Real domain;
1522  SCIP_Real lb;
1523  SCIP_Real ub;
1524 
1525  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1526  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1527 
1528  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1529  {
1530  consdata->maxactdelta = SCIPinfinity(scip);
1531  consdata->maxactdeltavar = consdata->vars[v];
1532  break;
1533  }
1534 
1535  domain = ub - lb;
1536  delta = REALABS(consdata->vals[v]) * domain;
1537 
1538  if( delta > consdata->maxactdelta )
1539  {
1540  consdata->maxactdelta = delta;
1541  consdata->maxactdeltavar = consdata->vars[v];
1542  }
1543  }
1544 }
1545 
1546 
1547 /** updates activities for a change in a bound */
1548 static
1550  SCIP* scip, /**< SCIP data structure */
1551  SCIP_CONSDATA* consdata, /**< linear constraint data */
1552  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1553  SCIP_Real oldbound, /**< old bound of variable */
1554  SCIP_Real newbound, /**< new bound of variable */
1555  SCIP_Real val, /**< coefficient of constraint entry */
1556  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1557  SCIP_Bool global, /**< is it a global or a local bound change? */
1558  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1559  )
1560 {
1561  SCIP_Real* activity;
1562  SCIP_Real* lastactivity;
1563  int* activityposinf;
1564  int* activityneginf;
1565  int* activityposhuge;
1566  int* activityneghuge;
1567  SCIP_Real oldcontribution;
1568  SCIP_Real newcontribution;
1569  SCIP_Real delta;
1570  SCIP_Bool validact;
1571  SCIP_Bool finitenewbound;
1572  SCIP_Bool hugevalnewcont;
1573 
1574  assert(scip != NULL);
1575  assert(consdata != NULL);
1576  assert(global || (var != NULL));
1577  assert(consdata->validactivities);
1578  assert(consdata->minactivity < SCIP_INVALID);
1579  assert(consdata->maxactivity < SCIP_INVALID);
1580  assert(consdata->lastminactivity < SCIP_INVALID);
1581  assert(consdata->lastmaxactivity < SCIP_INVALID);
1582  assert(consdata->minactivityneginf >= 0);
1583  assert(consdata->minactivityposinf >= 0);
1584  assert(consdata->maxactivityneginf >= 0);
1585  assert(consdata->maxactivityposinf >= 0);
1586  assert(consdata->minactivityneghuge >= 0);
1587  assert(consdata->minactivityposhuge >= 0);
1588  assert(consdata->maxactivityneghuge >= 0);
1589  assert(consdata->maxactivityposhuge >= 0);
1590  assert(consdata->glbminactivity < SCIP_INVALID);
1591  assert(consdata->glbmaxactivity < SCIP_INVALID);
1592  assert(consdata->lastglbminactivity < SCIP_INVALID);
1593  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1594  assert(consdata->glbminactivityneginf >= 0);
1595  assert(consdata->glbminactivityposinf >= 0);
1596  assert(consdata->glbmaxactivityneginf >= 0);
1597  assert(consdata->glbmaxactivityposinf >= 0);
1598  assert(consdata->glbminactivityneghuge >= 0);
1599  assert(consdata->glbminactivityposhuge >= 0);
1600  assert(consdata->glbmaxactivityneghuge >= 0);
1601  assert(consdata->glbmaxactivityposhuge >= 0);
1602 
1603  delta = 0.0;
1604 
1605  /* we are updating global activities */
1606  if( global )
1607  {
1608  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1609  * lower bound + pos. coef: update minactivity
1610  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1611  * upper bound + pos. coef: update maxactivity
1612  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1613  */
1614  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1615  {
1616  if( val > 0.0 )
1617  {
1618  activity = &(consdata->glbminactivity);
1619  lastactivity = &(consdata->lastglbminactivity);
1620  activityposinf = &(consdata->glbminactivityposinf);
1621  activityneginf = &(consdata->glbminactivityneginf);
1622  activityposhuge = &(consdata->glbminactivityposhuge);
1623  activityneghuge = &(consdata->glbminactivityneghuge);
1624  validact = consdata->validglbminact;
1625  }
1626  else
1627  {
1628  activity = &(consdata->glbmaxactivity);
1629  lastactivity = &(consdata->lastglbmaxactivity);
1630  activityposinf = &(consdata->glbmaxactivityneginf);
1631  activityneginf = &(consdata->glbmaxactivityposinf);
1632  activityposhuge = &(consdata->glbmaxactivityposhuge);
1633  activityneghuge = &(consdata->glbmaxactivityneghuge);
1634  validact = consdata->validglbmaxact;
1635  }
1636  }
1637  else
1638  {
1639  if( val > 0.0 )
1640  {
1641  activity = &(consdata->glbmaxactivity);
1642  lastactivity = &(consdata->lastglbmaxactivity);
1643  activityposinf = &(consdata->glbmaxactivityposinf);
1644  activityneginf = &(consdata->glbmaxactivityneginf);
1645  activityposhuge = &(consdata->glbmaxactivityposhuge);
1646  activityneghuge = &(consdata->glbmaxactivityneghuge);
1647  validact = consdata->validglbmaxact;
1648  }
1649  else
1650  {
1651  activity = &(consdata->glbminactivity);
1652  lastactivity = &(consdata->lastglbminactivity);
1653  activityposinf = &(consdata->glbminactivityneginf);
1654  activityneginf = &(consdata->glbminactivityposinf);
1655  activityposhuge = &(consdata->glbminactivityposhuge);
1656  activityneghuge = &(consdata->glbminactivityneghuge);
1657  validact = consdata->validglbminact;
1658  }
1659  }
1660  }
1661  /* we are updating local activities */
1662  else
1663  {
1664  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1665  * lower bound + pos. coef: update minactivity
1666  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1667  * upper bound + pos. coef: update maxactivity
1668  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1669  */
1670  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1671  {
1672  if( val > 0.0 )
1673  {
1674  activity = &(consdata->minactivity);
1675  lastactivity = &(consdata->lastminactivity);
1676  activityposinf = &(consdata->minactivityposinf);
1677  activityneginf = &(consdata->minactivityneginf);
1678  activityposhuge = &(consdata->minactivityposhuge);
1679  activityneghuge = &(consdata->minactivityneghuge);
1680  validact = consdata->validminact;
1681  }
1682  else
1683  {
1684  activity = &(consdata->maxactivity);
1685  lastactivity = &(consdata->lastmaxactivity);
1686  activityposinf = &(consdata->maxactivityneginf);
1687  activityneginf = &(consdata->maxactivityposinf);
1688  activityposhuge = &(consdata->maxactivityposhuge);
1689  activityneghuge = &(consdata->maxactivityneghuge);
1690  validact = consdata->validmaxact;
1691  }
1692  }
1693  else
1694  {
1695  if( val > 0.0 )
1696  {
1697  activity = &(consdata->maxactivity);
1698  lastactivity = &(consdata->lastmaxactivity);
1699  activityposinf = &(consdata->maxactivityposinf);
1700  activityneginf = &(consdata->maxactivityneginf);
1701  activityposhuge = &(consdata->maxactivityposhuge);
1702  activityneghuge = &(consdata->maxactivityneghuge);
1703  validact = consdata->validmaxact;
1704  }
1705  else
1706  {
1707  activity = &(consdata->minactivity);
1708  lastactivity = &(consdata->lastminactivity);
1709  activityposinf = &(consdata->minactivityneginf);
1710  activityneginf = &(consdata->minactivityposinf);
1711  activityposhuge = &(consdata->minactivityposhuge);
1712  activityneghuge = &(consdata->minactivityneghuge);
1713  validact = consdata->validminact;
1714  }
1715  }
1716  }
1717 
1718  oldcontribution = val * oldbound;
1719  newcontribution = val * newbound;
1720  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1721  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1722 
1723  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1724  {
1725  /* old bound was +infinity */
1726  if( oldbound > 0.0 )
1727  {
1728  assert((*activityposinf) >= 1);
1729 
1730  /* we only have to do something if the new bound is not again +infinity */
1731  if( finitenewbound || newbound < 0.0 )
1732  {
1733  /* decrease the counter for positive infinite contributions */
1734  (*activityposinf)--;
1735 
1736  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1737  if( !finitenewbound && newbound < 0.0 )
1738  (*activityneginf)++;
1739  else if( hugevalnewcont )
1740  {
1741  /* if the contribution of this variable is too large, increase the counter for huge values */
1742  if( newcontribution > 0.0 )
1743  (*activityposhuge)++;
1744  else
1745  (*activityneghuge)++;
1746  }
1747  /* "normal case": just add the contribution to the activity */
1748  else
1749  delta = newcontribution;
1750  }
1751  }
1752  /* old bound was -infinity */
1753  else
1754  {
1755  assert(oldbound < 0.0);
1756  assert((*activityneginf) >= 1);
1757 
1758  /* we only have to do something ig the new bound is not again -infinity */
1759  if( finitenewbound || newbound > 0.0 )
1760  {
1761  /* decrease the counter for negative infinite contributions */
1762  (*activityneginf)--;
1763 
1764  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1765  if( !finitenewbound && newbound > 0.0 )
1766  (*activityposinf)++;
1767  else if( hugevalnewcont )
1768  {
1769  /* if the contribution of this variable is too large, increase the counter for huge values */
1770  if( newcontribution > 0.0 )
1771  (*activityposhuge)++;
1772  else
1773  (*activityneghuge)++;
1774  }
1775  /* "normal case": just add the contribution to the activity */
1776  else
1777  delta = newcontribution;
1778  }
1779  }
1780  }
1781  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1782  {
1783  /* old contribution was too large and positive */
1784  if( oldcontribution > 0.0 )
1785  {
1786  assert((*activityposhuge) >= 1);
1787 
1788  /* decrease the counter for huge positive contributions; it might be increased again later,
1789  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1790  */
1791  (*activityposhuge)--;
1792 
1793  if( !finitenewbound )
1794  {
1795  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1796  if( newbound > 0.0 )
1797  (*activityposinf)++;
1798  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1799  else
1800  (*activityneginf)++;
1801  }
1802  else if( hugevalnewcont )
1803  {
1804  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1805  if( newcontribution > 0.0 )
1806  (*activityposhuge)++;
1807  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1808  else
1809  (*activityneghuge)++;
1810  }
1811  /* "normal case": just add the contribution to the activity */
1812  else
1813  delta = newcontribution;
1814  }
1815  /* old contribution was too large and negative */
1816  else
1817  {
1818  assert(oldcontribution < 0.0);
1819  assert((*activityneghuge) >= 1);
1820 
1821  /* decrease the counter for huge negative contributions; it might be increased again later,
1822  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1823  */
1824  (*activityneghuge)--;
1825 
1826  if( !finitenewbound )
1827  {
1828  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1829  if( newbound > 0.0 )
1830  (*activityposinf)++;
1831  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1832  else
1833  (*activityneginf)++;
1834  }
1835  else if( hugevalnewcont )
1836  {
1837  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1838  if( newcontribution > 0.0 )
1839  (*activityposhuge)++;
1840  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1841  else
1842  (*activityneghuge)++;
1843  }
1844  /* "normal case": just add the contribution to the activity */
1845  else
1846  delta = newcontribution;
1847  }
1848  }
1849  /* old bound was finite and not too large */
1850  else
1851  {
1852  if( !finitenewbound )
1853  {
1854  /* if the new bound is +infinity, the old contribution has to be subtracted
1855  * and the counter for positive infinite contributions has to be increased
1856  */
1857  if( newbound > 0.0 )
1858  {
1859  (*activityposinf)++;
1860  delta = -oldcontribution;
1861  }
1862  /* if the new bound is -infinity, the old contribution has to be subtracted
1863  * and the counter for negative infinite contributions has to be increased
1864  */
1865  else
1866  {
1867  assert(newbound < 0.0 );
1868 
1869  (*activityneginf)++;
1870  delta = -oldcontribution;
1871  }
1872  }
1873  /* if the contribution of this variable is too large, increase the counter for huge values */
1874  else if( hugevalnewcont )
1875  {
1876  if( newcontribution > 0.0 )
1877  {
1878  (*activityposhuge)++;
1879  delta = -oldcontribution;
1880  }
1881  else
1882  {
1883  (*activityneghuge)++;
1884  delta = -oldcontribution;
1885  }
1886  }
1887  /* "normal case": just update the activity */
1888  else
1889  delta = newcontribution - oldcontribution;
1890  }
1891 
1892  /* update the activity, if the current value is valid and there was a change in the finite part */
1893  if( validact && (delta != 0.0) )
1894  {
1895  /* if the absolute value of the activity is increased, this is regarded as reliable,
1896  * otherwise, we check whether we can still trust the updated value
1897  */
1898  (*activity) = (*activity) + delta;
1899  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1900 
1901  if( REALABS((*lastactivity)) < REALABS(*activity) )
1902  {
1903  (*lastactivity) = (*activity);
1904  }
1905  else
1906  {
1907  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1908  {
1909  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1910  (global ? "global " : ""), (*activity));
1911 
1912  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1913  if( global )
1914  {
1915  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1916  consdata->validglbminact = FALSE;
1917  else
1918  consdata->validglbmaxact = FALSE;
1919  }
1920  else
1921  {
1922  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1923  consdata->validminact = FALSE;
1924  else
1925  consdata->validmaxact = FALSE;
1926  }
1927  }
1928  }
1929  }
1930 }
1931 
1932 /** updates minimum and maximum activity for a change in lower bound */
1933 static
1935  SCIP* scip, /**< SCIP data structure */
1936  SCIP_CONSDATA* consdata, /**< linear constraint data */
1937  SCIP_VAR* var, /**< variable that has been changed */
1938  SCIP_Real oldlb, /**< old lower bound of variable */
1939  SCIP_Real newlb, /**< new lower bound of variable */
1940  SCIP_Real val, /**< coefficient of constraint entry */
1941  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1942  )
1943 {
1944  assert(scip != NULL);
1945  assert(consdata != NULL);
1946  assert(var != NULL);
1947 
1948  if( consdata->validactivities )
1949  {
1950  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1952  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1953  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1954  }
1955 }
1956 
1957 /** updates minimum and maximum activity for a change in upper bound */
1958 static
1960  SCIP* scip, /**< SCIP data structure */
1961  SCIP_CONSDATA* consdata, /**< linear constraint data */
1962  SCIP_VAR* var, /**< variable that has been changed */
1963  SCIP_Real oldub, /**< old upper bound of variable */
1964  SCIP_Real newub, /**< new upper bound of variable */
1965  SCIP_Real val, /**< coefficient of constraint entry */
1966  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1967  )
1968 {
1969  assert(scip != NULL);
1970  assert(consdata != NULL);
1971  assert(var != NULL);
1972 
1973  if( consdata->validactivities )
1974  {
1975  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
1977  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1978  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1979  }
1980 }
1981 
1982 /** updates minimum and maximum global activity for a change in the global lower bound */
1983 static
1985  SCIP* scip, /**< SCIP data structure */
1986  SCIP_CONSDATA* consdata, /**< linear constraint data */
1987  SCIP_Real oldlb, /**< old lower bound of variable */
1988  SCIP_Real newlb, /**< new lower bound of variable */
1989  SCIP_Real val, /**< coefficient of constraint entry */
1990  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1991  )
1992 {
1993  assert(scip != NULL);
1994  assert(consdata != NULL);
1995 
1996  if( consdata->validactivities )
1997  {
1998  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
1999 
2000  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2001  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2002  }
2003 }
2004 
2005 /** updates minimum and maximum global activity for a change in global upper bound */
2006 static
2008  SCIP* scip, /**< SCIP data structure */
2009  SCIP_CONSDATA* consdata, /**< linear constraint data */
2010  SCIP_Real oldub, /**< old upper bound of variable */
2011  SCIP_Real newub, /**< new upper bound of variable */
2012  SCIP_Real val, /**< coefficient of constraint entry */
2013  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2014  )
2015 {
2016  assert(scip != NULL);
2017  assert(consdata != NULL);
2018 
2019  if( consdata->validactivities )
2020  {
2021  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2022 
2023  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2024  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2025  }
2026 }
2027 
2028 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2029 static
2031  SCIP* scip, /**< SCIP data structure */
2032  SCIP_CONSDATA* consdata, /**< linear constraint data */
2033  SCIP_VAR* var, /**< variable of constraint entry */
2034  SCIP_Real val, /**< coefficient of constraint entry */
2035  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2036  )
2037 {
2038  assert(scip != NULL);
2039  assert(consdata != NULL);
2040  assert(var != NULL);
2041 
2042  /* update maximum absolute value */
2043  if( consdata->validmaxabsval )
2044  {
2045  SCIP_Real absval;
2046 
2047  assert(consdata->maxabsval < SCIP_INVALID);
2048 
2049  absval = REALABS(val);
2050  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2051  }
2052 
2053  if( consdata->validminabsval )
2054  {
2055  SCIP_Real absval;
2056 
2057  assert(consdata->minabsval < SCIP_INVALID);
2058 
2059  absval = REALABS(val);
2060  consdata->minabsval = MIN(consdata->minabsval, absval);
2061  }
2062 
2063  /* update minimal and maximal activity */
2064  if( consdata->validactivities )
2065  {
2066  assert(consdata->minactivity < SCIP_INVALID);
2067  assert(consdata->maxactivity < SCIP_INVALID);
2068  assert(consdata->glbminactivity < SCIP_INVALID);
2069  assert(consdata->glbmaxactivity < SCIP_INVALID);
2070 
2071  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2072  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2073  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2074  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2075  }
2076 }
2077 
2078 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2079 static
2081  SCIP* scip, /**< SCIP data structure */
2082  SCIP_CONSDATA* consdata, /**< linear constraint data */
2083  SCIP_VAR* var, /**< variable of constraint entry */
2084  SCIP_Real val, /**< coefficient of constraint entry */
2085  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2086  )
2087 {
2088  assert(scip != NULL);
2089  assert(consdata != NULL);
2090  assert(var != NULL);
2091 
2092  /* invalidate maximum absolute value, if this coefficient was the maximum */
2093  if( consdata->validmaxabsval )
2094  {
2095  SCIP_Real absval;
2096 
2097  absval = REALABS(val);
2098 
2099  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2100  {
2101  consdata->validmaxabsval = FALSE;
2102  consdata->maxabsval = SCIP_INVALID;
2103  }
2104  }
2105 
2106  /* invalidate minimum absolute value, if this coefficient was the minimum */
2107  if( consdata->validminabsval )
2108  {
2109  SCIP_Real absval;
2110 
2111  absval = REALABS(val);
2112 
2113  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2114  {
2115  consdata->validminabsval = FALSE;
2116  consdata->minabsval = SCIP_INVALID;
2117  }
2118  }
2119 
2120  /* update minimal and maximal activity */
2121  if( consdata->validactivities )
2122  {
2123  assert(consdata->minactivity < SCIP_INVALID);
2124  assert(consdata->maxactivity < SCIP_INVALID);
2125  assert(consdata->glbminactivity < SCIP_INVALID);
2126  assert(consdata->glbmaxactivity < SCIP_INVALID);
2127 
2128  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2129  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2130  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2131  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2132  }
2133 }
2134 
2135 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2136 static
2138  SCIP* scip, /**< SCIP data structure */
2139  SCIP_CONSDATA* consdata, /**< linear constraint data */
2140  SCIP_VAR* var, /**< variable of constraint entry */
2141  SCIP_Real oldval, /**< old coefficient of constraint entry */
2142  SCIP_Real newval, /**< new coefficient of constraint entry */
2143  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2144  )
2145 {
2146  assert(scip != NULL);
2147  assert(consdata != NULL);
2148  assert(var != NULL);
2149 
2150  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2151  assert(!SCIPisZero(scip, oldval));
2152 
2153  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2154  assert(!SCIPisZero(scip, newval));
2155 
2156  /* update maximum absolute value */
2157  if( consdata->validmaxabsval )
2158  {
2159  SCIP_Real absval;
2160 
2161  absval = REALABS(newval);
2162 
2163  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2164  {
2165  consdata->maxabsval = absval;
2166  }
2167  else
2168  {
2169  absval = REALABS(oldval);
2170 
2171  /* invalidate maximum absolute value */
2172  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2173  {
2174  consdata->validmaxabsval = FALSE;
2175  consdata->maxabsval = SCIP_INVALID;
2176  }
2177  }
2178  }
2179 
2180  /* update minimum absolute value */
2181  if( consdata->validminabsval )
2182  {
2183  SCIP_Real absval;
2184 
2185  absval = REALABS(newval);
2186 
2187  if( SCIPisLE(scip, absval, consdata->minabsval) )
2188  {
2189  consdata->minabsval = absval;
2190  }
2191  else
2192  {
2193  absval = REALABS(oldval);
2194 
2195  /* invalidate minimum absolute value */
2196  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2197  {
2198  consdata->validminabsval = FALSE;
2199  consdata->minabsval = SCIP_INVALID;
2200  }
2201  }
2202  }
2203 
2204 
2205  /* update maximum activity delta */
2206  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2207  {
2208  SCIP_Real domain;
2209  SCIP_Real delta;
2210 
2211  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2212  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2213 
2214  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2215  delta = REALABS(newval) * domain;
2216 
2217  if( delta > consdata->maxactdelta )
2218  {
2219  consdata->maxactdelta = delta;
2220  consdata->maxactdeltavar = var;
2221  }
2222  else
2223  {
2224  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2225  if( consdata->maxactdeltavar == var )
2226  consdata->maxactdelta = SCIP_INVALID;
2227  }
2228  }
2229 
2230  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2231  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2232  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2233 }
2234 
2235 /** returns the maximum absolute value of all coefficients in the constraint */
2236 static
2238  SCIP_CONSDATA* consdata /**< linear constraint data */
2239  )
2240 {
2241  assert(consdata != NULL);
2242 
2243  if( !consdata->validmaxabsval )
2244  consdataCalcMaxAbsval(consdata);
2245  assert(consdata->validmaxabsval);
2246  assert(consdata->maxabsval < SCIP_INVALID);
2247 
2248  return consdata->maxabsval;
2249 }
2250 
2251 /** returns the minimum absolute value of all coefficients in the constraint */
2252 static
2254  SCIP_CONSDATA* consdata /**< linear constraint data */
2255  )
2256 {
2257  assert(consdata != NULL);
2258 
2259  if( !consdata->validminabsval )
2260  consdataCalcMinAbsval(consdata);
2261  assert(consdata->validminabsval);
2262  assert(consdata->minabsval < SCIP_INVALID);
2263 
2264  return consdata->minabsval;
2265 }
2266 
2267 /** calculates minimum and maximum local and global activity for constraint from scratch;
2268  * additionally recalculates maximum absolute value of coefficients
2269  */
2270 static
2272  SCIP* scip, /**< SCIP data structure */
2273  SCIP_CONSDATA* consdata /**< linear constraint data */
2274  )
2275 {
2276  int i;
2277 
2278  assert(scip != NULL);
2279  assert(consdata != NULL);
2280  assert(!consdata->validactivities);
2281  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2282  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2283  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2284  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2285 
2286  consdata->validmaxabsval = TRUE;
2287  consdata->validminabsval = TRUE;
2288  consdata->validactivities = TRUE;
2289  consdata->validminact = TRUE;
2290  consdata->validmaxact = TRUE;
2291  consdata->validglbminact = TRUE;
2292  consdata->validglbmaxact = TRUE;
2293  consdata->maxabsval = 0.0;
2294  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2295  consdata->minactivity = 0.0;
2296  consdata->maxactivity = 0.0;
2297  consdata->lastminactivity = 0.0;
2298  consdata->lastmaxactivity = 0.0;
2299  consdata->minactivityneginf = 0;
2300  consdata->minactivityposinf = 0;
2301  consdata->maxactivityneginf = 0;
2302  consdata->maxactivityposinf = 0;
2303  consdata->minactivityneghuge = 0;
2304  consdata->minactivityposhuge = 0;
2305  consdata->maxactivityneghuge = 0;
2306  consdata->maxactivityposhuge = 0;
2307  consdata->glbminactivity = 0.0;
2308  consdata->glbmaxactivity = 0.0;
2309  consdata->lastglbminactivity = 0.0;
2310  consdata->lastglbmaxactivity = 0.0;
2311  consdata->glbminactivityneginf = 0;
2312  consdata->glbminactivityposinf = 0;
2313  consdata->glbmaxactivityneginf = 0;
2314  consdata->glbmaxactivityposinf = 0;
2315  consdata->glbminactivityneghuge = 0;
2316  consdata->glbminactivityposhuge = 0;
2317  consdata->glbmaxactivityneghuge = 0;
2318  consdata->glbmaxactivityposhuge = 0;
2319 
2320  for( i = 0; i < consdata->nvars; ++i )
2321  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2322 
2323  consdata->lastminactivity = consdata->minactivity;
2324  consdata->lastmaxactivity = consdata->maxactivity;
2325  consdata->lastglbminactivity = consdata->glbminactivity;
2326  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2327 }
2328 
2329 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2330  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2331  */
2332 static
2333 void getMinActivity(
2334  SCIP* scip, /**< SCIP data structure */
2335  SCIP_CONSDATA* consdata, /**< linear constraint */
2336  int posinf, /**< number of coefficients contributing pos. infinite value */
2337  int neginf, /**< number of coefficients contributing neg. infinite value */
2338  int poshuge, /**< number of coefficients contributing huge pos. value */
2339  int neghuge, /**< number of coefficients contributing huge neg. value */
2340  SCIP_Real delta, /**< value to subtract from stored minactivity
2341  * (contribution of the variable set to zero when getting residual activity) */
2342  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2343  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2344  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2345  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2346  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2347  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2348  )
2349 {
2350  assert(scip != NULL);
2351  assert(consdata != NULL);
2352  assert(posinf >= 0);
2353  assert(neginf >= 0);
2354  assert(poshuge >= 0);
2355  assert(neghuge >= 0);
2356  assert(minactivity != NULL);
2357  assert(isrelax != NULL);
2358  assert(issettoinfinity != NULL);
2359 
2360  /* if we have pos. infinite contributions, the minactivity is +infty */
2361  if( posinf > 0 )
2362  {
2363  *minactivity = SCIPinfinity(scip);
2364  *issettoinfinity = TRUE;
2365  *isrelax = FALSE;
2366  }
2367  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2368  else if( neginf > 0 )
2369  {
2370  *minactivity = -SCIPinfinity(scip);
2371  *issettoinfinity = TRUE;
2372  *isrelax = FALSE;
2373  }
2374  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2375  else if( neghuge > 0 )
2376  {
2377  *minactivity = -SCIPinfinity(scip);
2378  *issettoinfinity = TRUE;
2379  *isrelax = TRUE;
2380  }
2381  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2382  else if( !goodrelax && poshuge > 0 )
2383  {
2384  *minactivity = -SCIPinfinity(scip);
2385  *issettoinfinity = TRUE;
2386  *isrelax = TRUE;
2387  }
2388  else
2389  {
2390  SCIP_Real tmpactivity;
2391 
2392  /* recompute minactivity if it is not valid */
2393  if( global )
2394  {
2395  if( !consdata->validglbminact )
2396  consdataRecomputeGlbMinactivity(scip, consdata);
2397  assert(consdata->validglbminact);
2398 
2399  tmpactivity = consdata->glbminactivity;
2400  }
2401  else
2402  {
2403  if( !consdata->validminact )
2404  consdataRecomputeMinactivity(scip, consdata);
2405  assert(consdata->validminact);
2406 
2407  tmpactivity = consdata->minactivity;
2408  }
2409 
2410  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2411  * a feasible relaxation of the minactivity is the number of positive huge contributions
2412  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2413  */
2414  if( poshuge > 0 )
2415  {
2416  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2417  *issettoinfinity = FALSE;
2418  *isrelax = TRUE;
2419  }
2420  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2421  else
2422  {
2423  *minactivity = tmpactivity - delta;
2424  *issettoinfinity = FALSE;
2425  *isrelax = FALSE;
2426  }
2427  }
2428 }
2429 
2430 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2431  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2432  */
2433 static
2434 void getMaxActivity(
2435  SCIP* scip, /**< SCIP data structure */
2436  SCIP_CONSDATA* consdata, /**< linear constraint */
2437  int posinf, /**< number of coefficients contributing pos. infinite value */
2438  int neginf, /**< number of coefficients contributing neg. infinite value */
2439  int poshuge, /**< number of coefficients contributing huge pos. value */
2440  int neghuge, /**< number of coefficients contributing huge neg. value */
2441  SCIP_Real delta, /**< value to subtract from stored maxactivity
2442  * (contribution of the variable set to zero when getting residual activity) */
2443  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2444  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2445  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2446  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2447  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2448  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2449  )
2450 {
2451  assert(scip != NULL);
2452  assert(consdata != NULL);
2453  assert(posinf >= 0);
2454  assert(neginf >= 0);
2455  assert(poshuge >= 0);
2456  assert(neghuge >= 0);
2457  assert(maxactivity != NULL);
2458  assert(isrelax != NULL);
2459  assert(issettoinfinity != NULL);
2460 
2461  /* if we have neg. infinite contributions, the maxactivity is -infty */
2462  if( neginf > 0 )
2463  {
2464  *maxactivity = -SCIPinfinity(scip);
2465  *issettoinfinity = TRUE;
2466  *isrelax = FALSE;
2467  }
2468  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2469  else if( posinf > 0 )
2470  {
2471  *maxactivity = SCIPinfinity(scip);
2472  *issettoinfinity = TRUE;
2473  *isrelax = FALSE;
2474  }
2475  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2476  else if( poshuge > 0 )
2477  {
2478  *maxactivity = SCIPinfinity(scip);
2479  *issettoinfinity = TRUE;
2480  *isrelax = TRUE;
2481  }
2482  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2483  else if( !goodrelax && neghuge > 0 )
2484  {
2485  *maxactivity = SCIPinfinity(scip);
2486  *issettoinfinity = TRUE;
2487  *isrelax = TRUE;
2488  }
2489  else
2490  {
2491  SCIP_Real tmpactivity;
2492 
2493  /* recompute maxactivity if it is not valid */
2494  if( global )
2495  {
2496  if( !consdata->validglbmaxact )
2497  consdataRecomputeGlbMaxactivity(scip, consdata);
2498  assert(consdata->validglbmaxact);
2499 
2500  tmpactivity = consdata->glbmaxactivity;
2501  }
2502  else
2503  {
2504  if( !consdata->validmaxact )
2505  consdataRecomputeMaxactivity(scip, consdata);
2506  assert(consdata->validmaxact);
2507 
2508  tmpactivity = consdata->maxactivity;
2509  }
2510 
2511  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2512  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2513  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2514  */
2515  if( neghuge > 0 )
2516  {
2517  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2518  *issettoinfinity = FALSE;
2519  *isrelax = TRUE;
2520  }
2521  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2522  else
2523  {
2524  *maxactivity = tmpactivity - delta;
2525  *issettoinfinity = FALSE;
2526  *isrelax = FALSE;
2527  }
2528  }
2529 }
2530 
2531 /** gets activity bounds for constraint */
2532 static
2534  SCIP* scip, /**< SCIP data structure */
2535  SCIP_CONSDATA* consdata, /**< linear constraint */
2536  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2537  * relaxed acticities ignored, anyway? */
2538  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2539  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2540  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2541  * i.e. <= the exact minactivity (in case of huge contributions),
2542  * or equal to the exact minimal activity */
2543  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2544  * i.e. >= the exact maxactivity (in case of huge contributions),
2545  * or equal to the exact maximal activity */
2546  )
2547 {
2548  SCIP_Bool issettoinfinity;
2549 
2550  assert(scip != NULL);
2551  assert(consdata != NULL);
2552  assert(minactivity != NULL);
2553  assert(maxactivity != NULL);
2554 
2555  if( !consdata->validactivities )
2556  {
2557  consdataCalcActivities(scip, consdata);
2558  assert(consdata->validminact);
2559  assert(consdata->validmaxact);
2560  }
2561  assert(consdata->minactivity < SCIP_INVALID);
2562  assert(consdata->maxactivity < SCIP_INVALID);
2563  assert(consdata->minactivityneginf >= 0);
2564  assert(consdata->minactivityposinf >= 0);
2565  assert(consdata->maxactivityneginf >= 0);
2566  assert(consdata->maxactivityposinf >= 0);
2567 
2568  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2569  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2570  minactivity, minisrelax, &issettoinfinity);
2571 
2572  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2573  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2574  maxactivity, maxisrelax, &issettoinfinity);
2575 }
2576 
2577 /** calculates activity bounds for constraint after setting variable to zero */
2578 static
2580  SCIP* scip, /**< SCIP data structure */
2581  SCIP_CONSDATA* consdata, /**< linear constraint */
2582  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2583  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2584  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2585  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2586  )
2587 {
2588  SCIP_VAR* var;
2589  SCIP_Real val;
2590  SCIP_Real lb;
2591  SCIP_Real ub;
2592  int v;
2593 
2594  assert(scip != NULL);
2595  assert(consdata != NULL);
2596  assert(cancelvar != NULL);
2597  assert(resactivity != NULL);
2598 
2599  *resactivity = 0.0;
2600 
2601  for( v = 0; v < consdata->nvars; ++v )
2602  {
2603  var = consdata->vars[v];
2604  assert(var != NULL);
2605  if( var == cancelvar )
2606  continue;
2607 
2608  val = consdata->vals[v];
2609 
2610  if( useglobalbounds )
2611  {
2612  lb = SCIPvarGetLbGlobal(var);
2613  ub = SCIPvarGetUbGlobal(var);
2614  }
2615  else
2616  {
2617  lb = SCIPvarGetLbLocal(var);
2618  ub = SCIPvarGetUbLocal(var);
2619  }
2620 
2621  assert(!SCIPisZero(scip, val));
2622  assert(SCIPisLE(scip, lb, ub));
2623 
2624  if( val > 0.0 )
2625  {
2626  if( isminresact )
2627  {
2628  assert(!SCIPisInfinity(scip, -lb));
2629  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2630  *resactivity += val*lb;
2631  }
2632  else
2633  {
2634  assert(!SCIPisInfinity(scip, ub));
2635  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2636  *resactivity += val*ub;
2637  }
2638  }
2639  else
2640  {
2641  if( isminresact)
2642  {
2643  assert(!SCIPisInfinity(scip, ub));
2644  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2645  *resactivity += val*ub;
2646  }
2647  else
2648  {
2649  assert(!SCIPisInfinity(scip, -lb));
2650  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2651  *resactivity += val*lb;
2652  }
2653  }
2654  }
2655  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2656 }
2657 
2658 /** gets activity bounds for constraint after setting variable to zero */
2659 static
2661  SCIP* scip, /**< SCIP data structure */
2662  SCIP_CONSDATA* consdata, /**< linear constraint */
2663  SCIP_VAR* var, /**< variable to calculate activity residual for */
2664  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2665  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2666  * relaxed acticities ignored, anyway? */
2667  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2668  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2669  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2670  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2671  * contributions), or equal to the exact residual minactivity */
2672  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2673  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2674  * contributions), or equal to the exact residual minactivity */
2675  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2676  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2677  )
2678 {
2679  SCIP_Real minactbound;
2680  SCIP_Real maxactbound;
2681  SCIP_Real absval;
2682 
2683  assert(scip != NULL);
2684  assert(consdata != NULL);
2685  assert(var != NULL);
2686  assert(minresactivity != NULL);
2687  assert(maxresactivity != NULL);
2688  assert(minisrelax != NULL);
2689  assert(maxisrelax != NULL);
2690  assert(isminsettoinfinity != NULL);
2691  assert(ismaxsettoinfinity != NULL);
2692 
2693  /* get activity bounds of linear constraint */
2694  if( !consdata->validactivities )
2695  {
2696  consdataCalcActivities(scip, consdata);
2697  assert(consdata->validminact);
2698  assert(consdata->validmaxact);
2699  }
2700  assert(consdata->minactivity < SCIP_INVALID);
2701  assert(consdata->maxactivity < SCIP_INVALID);
2702  assert(consdata->minactivityneginf >= 0);
2703  assert(consdata->minactivityposinf >= 0);
2704  assert(consdata->maxactivityneginf >= 0);
2705  assert(consdata->maxactivityposinf >= 0);
2706  assert(consdata->minactivityneghuge >= 0);
2707  assert(consdata->minactivityposhuge >= 0);
2708  assert(consdata->maxactivityneghuge >= 0);
2709  assert(consdata->maxactivityposhuge >= 0);
2710 
2711  if( val > 0.0 )
2712  {
2713  minactbound = SCIPvarGetLbLocal(var);
2714  maxactbound = SCIPvarGetUbLocal(var);
2715  absval = val;
2716  }
2717  else
2718  {
2719  minactbound = -SCIPvarGetUbLocal(var);
2720  maxactbound = -SCIPvarGetLbLocal(var);
2721  absval = -val;
2722  }
2723 
2724  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2725  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2726  */
2727  if( SCIPisInfinity(scip, minactbound) )
2728  {
2729  assert(consdata->minactivityposinf >= 1);
2730 
2731  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2732  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2733  minresactivity, minisrelax, isminsettoinfinity);
2734  }
2735  else if( SCIPisInfinity(scip, -minactbound) )
2736  {
2737  assert(consdata->minactivityneginf >= 1);
2738 
2739  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2740  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2741  minresactivity, minisrelax, isminsettoinfinity);
2742  }
2743  else if( SCIPisHugeValue(scip, minactbound * absval) )
2744  {
2745  assert(consdata->minactivityposhuge >= 1);
2746 
2747  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2748  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2749  minresactivity, minisrelax, isminsettoinfinity);
2750  }
2751  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2752  {
2753  assert(consdata->minactivityneghuge >= 1);
2754 
2755  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2756  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2757  minresactivity, minisrelax, isminsettoinfinity);
2758  }
2759  else
2760  {
2761  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2762  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2763  minresactivity, minisrelax, isminsettoinfinity);
2764  }
2765 
2766  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2767  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2768  */
2769  if( SCIPisInfinity(scip, -maxactbound) )
2770  {
2771  assert(consdata->maxactivityneginf >= 1);
2772 
2773  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2774  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2775  maxresactivity, maxisrelax, ismaxsettoinfinity);
2776  }
2777  else if( SCIPisInfinity(scip, maxactbound) )
2778  {
2779  assert(consdata->maxactivityposinf >= 1);
2780 
2781  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2782  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2783  maxresactivity, maxisrelax, ismaxsettoinfinity);
2784  }
2785  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2786  {
2787  assert(consdata->maxactivityposhuge >= 1);
2788 
2789  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2790  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2791  maxresactivity, maxisrelax, ismaxsettoinfinity);
2792  }
2793  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2794  {
2795  assert(consdata->maxactivityneghuge >= 1);
2796 
2797  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2798  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2799  maxresactivity, maxisrelax, ismaxsettoinfinity);
2800  }
2801  else
2802  {
2803  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2804  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2805  maxresactivity, maxisrelax, ismaxsettoinfinity);
2806  }
2807 }
2808 
2809 /** gets global activity bounds for constraint */
2810 static
2812  SCIP* scip, /**< SCIP data structure */
2813  SCIP_CONSDATA* consdata, /**< linear constraint */
2814  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2815  * relaxed acticities ignored, anyway? */
2816  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2817  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2818  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2819  * i.e. <= the exact minactivity (in case of huge contributions),
2820  * or equal to the exact minimal activity */
2821  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2822  * i.e. >= the exact maxactivity (in case of huge contributions),
2823  * or equal to the exact maximal activity */
2824  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2825  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2826  )
2827 {
2828  assert(scip != NULL);
2829  assert(consdata != NULL);
2830  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2831  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2832 
2833  if( !consdata->validactivities )
2834  {
2835  consdataCalcActivities(scip, consdata);
2836  assert(consdata->validglbminact);
2837  assert(consdata->validglbmaxact);
2838  }
2839  assert(consdata->glbminactivity < SCIP_INVALID);
2840  assert(consdata->glbmaxactivity < SCIP_INVALID);
2841  assert(consdata->glbminactivityneginf >= 0);
2842  assert(consdata->glbminactivityposinf >= 0);
2843  assert(consdata->glbmaxactivityneginf >= 0);
2844  assert(consdata->glbmaxactivityposinf >= 0);
2845  assert(consdata->glbminactivityneghuge >= 0);
2846  assert(consdata->glbminactivityposhuge >= 0);
2847  assert(consdata->glbmaxactivityneghuge >= 0);
2848  assert(consdata->glbmaxactivityposhuge >= 0);
2849 
2850  if( glbminactivity != NULL )
2851  {
2852  assert(isminsettoinfinity != NULL);
2853  assert(minisrelax != NULL);
2854 
2855  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2856  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2857  glbminactivity, minisrelax, isminsettoinfinity);
2858  }
2859 
2860  if( glbmaxactivity != NULL )
2861  {
2862  assert(ismaxsettoinfinity != NULL);
2863  assert(maxisrelax != NULL);
2864 
2865  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2866  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2867  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2868  }
2869 }
2870 
2871 /** gets global activity bounds for constraint after setting variable to zero */
2872 static
2874  SCIP* scip, /**< SCIP data structure */
2875  SCIP_CONSDATA* consdata, /**< linear constraint */
2876  SCIP_VAR* var, /**< variable to calculate activity residual for */
2877  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2878  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2879  * relaxed acticities ignored, anyway? */
2880  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2881  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2882  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2883  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2884  * contributions), or equal to the exact residual minactivity */
2885  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2886  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2887  * contributions), or equal to the exact residual minactivity */
2888  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2889  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2890  )
2891 {
2892  SCIP_Real minactbound;
2893  SCIP_Real maxactbound;
2894  SCIP_Real absval;
2895 
2896  assert(scip != NULL);
2897  assert(consdata != NULL);
2898  assert(var != NULL);
2899  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2900  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2901 
2902  /* get activity bounds of linear constraint */
2903  if( !consdata->validactivities )
2904  consdataCalcActivities(scip, consdata);
2905 
2906  assert(consdata->glbminactivity < SCIP_INVALID);
2907  assert(consdata->glbmaxactivity < SCIP_INVALID);
2908  assert(consdata->glbminactivityneginf >= 0);
2909  assert(consdata->glbminactivityposinf >= 0);
2910  assert(consdata->glbmaxactivityneginf >= 0);
2911  assert(consdata->glbmaxactivityposinf >= 0);
2912 
2913  if( val > 0.0 )
2914  {
2915  minactbound = SCIPvarGetLbGlobal(var);
2916  maxactbound = SCIPvarGetUbGlobal(var);
2917  absval = val;
2918  }
2919  else
2920  {
2921  minactbound = -SCIPvarGetUbGlobal(var);
2922  maxactbound = -SCIPvarGetLbGlobal(var);
2923  absval = -val;
2924  }
2925 
2926  if( minresactivity != NULL )
2927  {
2928  assert(isminsettoinfinity != NULL);
2929  assert(minisrelax != NULL);
2930 
2931  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2932  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2933  */
2934  if( SCIPisInfinity(scip, minactbound) )
2935  {
2936  assert(consdata->glbminactivityposinf >= 1);
2937 
2938  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2939  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2940  minresactivity, minisrelax, isminsettoinfinity);
2941  }
2942  else if( SCIPisInfinity(scip, -minactbound) )
2943  {
2944  assert(consdata->glbminactivityneginf >= 1);
2945 
2946  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2947  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2948  minresactivity, minisrelax, isminsettoinfinity);
2949  }
2950  else if( SCIPisHugeValue(scip, minactbound * absval) )
2951  {
2952  assert(consdata->glbminactivityposhuge >= 1);
2953 
2954  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2955  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2956  minresactivity, minisrelax, isminsettoinfinity);
2957  }
2958  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2959  {
2960  assert(consdata->glbminactivityneghuge >= 1);
2961 
2962  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2963  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2964  minresactivity, minisrelax, isminsettoinfinity);
2965  }
2966  else
2967  {
2968  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2969  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2970  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
2971  }
2972  }
2973 
2974  if( maxresactivity != NULL )
2975  {
2976  assert(ismaxsettoinfinity != NULL);
2977  assert(maxisrelax != NULL);
2978 
2979  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2980  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2981  */
2982  if( SCIPisInfinity(scip, -maxactbound) )
2983  {
2984  assert(consdata->glbmaxactivityneginf >= 1);
2985 
2986  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2987  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2988  maxresactivity, maxisrelax, ismaxsettoinfinity);
2989  }
2990  else if( SCIPisInfinity(scip, maxactbound) )
2991  {
2992  assert(consdata->glbmaxactivityposinf >= 1);
2993 
2994  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2995  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2996  maxresactivity, maxisrelax, ismaxsettoinfinity);
2997  }
2998  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2999  {
3000  assert(consdata->glbmaxactivityposhuge >= 1);
3001 
3002  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3003  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3004  maxresactivity, maxisrelax, ismaxsettoinfinity);
3005  }
3006  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3007  {
3008  assert(consdata->glbmaxactivityneghuge >= 1);
3009 
3010  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3011  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3012  maxresactivity, maxisrelax, ismaxsettoinfinity);
3013  }
3014  else
3015  {
3016  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3017  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3018  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3019  }
3020  }
3021 }
3022 
3023 /** calculates the activity of the linear constraint for given solution */
3024 static
3026  SCIP* scip, /**< SCIP data structure */
3027  SCIP_CONSDATA* consdata, /**< linear constraint data */
3028  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3029  )
3030 {
3031  SCIP_Real activity;
3032 
3033  assert(scip != NULL);
3034  assert(consdata != NULL);
3035 
3036  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3037  activity = consdataComputePseudoActivity(scip, consdata);
3038  else
3039  {
3040  SCIP_Real solval;
3041  int nposinf;
3042  int nneginf;
3043  SCIP_Bool negsign;
3044  int v;
3045 
3046  activity = 0.0;
3047  nposinf = 0;
3048  nneginf = 0;
3049 
3050  for( v = 0; v < consdata->nvars; ++v )
3051  {
3052  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3053 
3054  if( consdata->vals[v] < 0 )
3055  negsign = TRUE;
3056  else
3057  negsign = FALSE;
3058 
3059  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3060  ++nposinf;
3061  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3062  ++nneginf;
3063  else
3064  activity += consdata->vals[v] * solval;
3065  }
3066  assert(nneginf >= 0 && nposinf >= 0);
3067 
3068  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3069 
3070  /* check for amount of infinity values and correct the activity */
3071  if( nposinf > 0 && nneginf > 0 )
3072  activity = (consdata->rhs + consdata->lhs) / 2;
3073  else if( nposinf > 0 )
3074  activity = SCIPinfinity(scip);
3075  else if( nneginf > 0 )
3076  activity = -SCIPinfinity(scip);
3077 
3078  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3079  }
3080 
3081  if( activity == SCIP_INVALID ) /*lint !e777*/
3082  return activity;
3083  else if( activity < 0 )
3084  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3085  else
3086  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3087 
3088  return activity;
3089 }
3090 
3091 /** calculates the feasibility of the linear constraint for given solution */
3092 static
3094  SCIP* scip, /**< SCIP data structure */
3095  SCIP_CONSDATA* consdata, /**< linear constraint data */
3096  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3097  )
3098 {
3099  SCIP_Real activity;
3100 
3101  assert(scip != NULL);
3102  assert(consdata != NULL);
3103 
3104  activity = consdataGetActivity(scip, consdata, sol);
3105 
3106  if( activity == SCIP_INVALID ) /*lint !e777*/
3107  return -SCIPinfinity(scip);
3108 
3109  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3111 
3112 /** updates bit signatures after adding a single coefficient */
3113 static
3115  SCIP_CONSDATA* consdata, /**< linear constraint data */
3116  int pos /**< position of coefficient to update signatures for */
3117  )
3118 {
3119  uint64_t varsignature;
3120  SCIP_Real lb;
3121  SCIP_Real ub;
3122  SCIP_Real val;
3123 
3124  assert(consdata != NULL);
3125  assert(consdata->validsignature);
3126 
3127  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3128  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3129  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3130  val = consdata->vals[pos];
3131  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3132  consdata->possignature |= varsignature;
3133  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3134  consdata->negsignature |= varsignature;
3135 }
3136 
3137 /** calculates the bit signatures of the given constraint data */
3138 static
3140  SCIP_CONSDATA* consdata /**< linear constraint data */
3141  )
3142 {
3143  assert(consdata != NULL);
3144 
3145  if( !consdata->validsignature )
3146  {
3147  int i;
3148 
3149  consdata->validsignature = TRUE;
3150  consdata->possignature = 0;
3151  consdata->negsignature = 0;
3152  for( i = 0; i < consdata->nvars; ++i )
3153  consdataUpdateSignatures(consdata, i);
3154  }
3155 }
3157 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3158 static
3159 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3160 { /*lint --e{715}*/
3161  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3162 
3163  assert(consdata != NULL);
3164  assert(0 <= ind1 && ind1 < consdata->nvars);
3165  assert(0 <= ind2 && ind2 < consdata->nvars);
3166 
3167  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3168 }
3169 
3170 /** permutes the constraint's variables according to a given permutation. */
3171 static
3172 void permSortConsdata(
3173  SCIP_CONSDATA* consdata, /**< the constraint data */
3174  int* perm, /**< the target permutation */
3175  int nvars /**< the number of variables */
3176  )
3177 { /*lint --e{715}*/
3178  SCIP_VAR* varv;
3179  SCIP_EVENTDATA* eventdatav;
3180  SCIP_Real valv;
3181  int v;
3182  int i;
3183  int nexti;
3184 
3185  assert(perm != NULL);
3186  assert(consdata != NULL);
3187 
3188  /* permute the variables in the linear constraint according to the target permutation */
3189  eventdatav = NULL;
3190  for( v = 0; v < nvars; ++v )
3191  {
3192  if( perm[v] != v )
3193  {
3194  varv = consdata->vars[v];
3195  valv = consdata->vals[v];
3196  if( consdata->eventdata != NULL )
3197  eventdatav = consdata->eventdata[v];
3198  i = v;
3199  do
3200  {
3201  assert(0 <= perm[i] && perm[i] < nvars);
3202  assert(perm[i] != i);
3203  consdata->vars[i] = consdata->vars[perm[i]];
3204  consdata->vals[i] = consdata->vals[perm[i]];
3205  if( consdata->eventdata != NULL )
3206  {
3207  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3208  consdata->eventdata[i]->varpos = i;
3209  }
3210  nexti = perm[i];
3211  perm[i] = i;
3212  i = nexti;
3213  }
3214  while( perm[i] != v );
3215  consdata->vars[i] = varv;
3216  consdata->vals[i] = valv;
3217  if( consdata->eventdata != NULL )
3218  {
3219  consdata->eventdata[i] = eventdatav;
3220  consdata->eventdata[i]->varpos = i;
3221  }
3222  perm[i] = i;
3223  }
3224  }
3225 #ifdef SCIP_DEBUG
3226  /* check sorting */
3227  for( v = 0; v < nvars; ++v )
3228  {
3229  assert(perm[v] == v);
3230  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3231  }
3232 #endif
3233 }
3234 
3235 /** sorts linear constraint's variables depending on the stage of the solving process:
3236  * - during PRESOLVING
3237  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3238  * and the variables of the same type by non-decreasing variable index
3239  *
3240  * - during SOLVING
3241  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3242  * This fastens the propagation time of the constraint handler.
3243  */
3244 static
3246  SCIP* scip, /**< SCIP data structure */
3247  SCIP_CONSDATA* consdata /**< linear constraint data */
3248  )
3249 {
3250  assert(scip != NULL);
3251  assert(consdata != NULL);
3252 
3253  /* check if there are variables for sorting */
3254  if( consdata->nvars <= 1 )
3255  {
3256  consdata->sorted = TRUE;
3257  consdata->binvarssorted = TRUE;
3258  }
3259  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3260  {
3261  int* perm;
3263  /* get temporary memory to store the sorted permutation */
3264  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3265 
3266  /* call sorting method */
3267  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3268 
3269  permSortConsdata(consdata, perm, consdata->nvars);
3270 
3271  /* free temporary memory */
3272  SCIPfreeBufferArray(scip, &perm);
3273 
3274  consdata->sorted = TRUE;
3275  consdata->binvarssorted = FALSE;
3276  }
3277  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3278  {
3279  SCIP_EVENTDATA** eventdata;
3280  SCIP_VAR** vars;
3281  SCIP_Real* vals;
3282  int nvars;
3283  int v;
3284  int lastbin;
3285 
3286  nvars = consdata->nvars;
3287  vars = consdata->vars;
3288  vals = consdata->vals;
3289  eventdata = consdata->eventdata;
3290  assert(vars != NULL || nvars == 0);
3291  assert(vals != NULL || nvars == 0);
3292 
3293  lastbin = 0;
3294  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3295  for( v = 0; v < nvars; ++v )
3296  {
3297  assert( vars != NULL); /* for flexelint */
3298  assert( vals != NULL); /* for flexelint */
3299  if( SCIPvarIsBinary(vars[v]) )
3300  {
3301  /* swap variable at the end of the binary variables, if necessary */
3302  if( lastbin < v )
3303  {
3304  SCIP_VAR* tmpvar;
3305  SCIP_Real tmpval;
3306 
3307  tmpvar = vars[lastbin];
3308  tmpval = vals[lastbin];
3309 
3310  vars[lastbin] = vars[v];
3311  vals[lastbin] = vals[v];
3312 
3313  vars[v] = tmpvar;
3314  vals[v] = tmpval;
3315 
3316  if( eventdata != NULL )
3317  {
3318  SCIP_EVENTDATA* tmpeventdata;
3319 
3320  tmpeventdata = eventdata[lastbin];
3321  eventdata[lastbin] = eventdata[v];
3322  eventdata[lastbin]->varpos = lastbin;
3323  eventdata[v] = tmpeventdata;
3324  eventdata[v]->varpos = v;
3325  }
3326  assert(SCIPvarIsBinary(vars[lastbin]));
3327  }
3328 #ifndef NDEBUG
3329  else
3330  assert(lastbin == v);
3331 #endif
3332  ++lastbin;
3333  }
3334  }
3335  consdata->nbinvars = lastbin;
3336 
3337 #ifndef NDEBUG
3338  /* check sorting */
3339  for( v = 0; v < nvars; ++v )
3340  {
3341  assert(vars != NULL); /* for flexelint */
3342  assert(eventdata == NULL || eventdata[v]->varpos == v);
3343  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3344  }
3345 #endif
3346 
3347  if( consdata->nbinvars > 1 )
3348  {
3349  SCIP_Real* absvals;
3350  int* perm;
3351 
3352  assert(lastbin == consdata->nbinvars);
3353  assert(lastbin <= nvars);
3354  assert(vals != NULL);
3355 
3356  /* initialize absolute coefficients and the target permutation for binary variables */
3357  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3358  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3359 
3360  for( v = 0; v < lastbin; ++v )
3361  {
3362  absvals[v] = ABS(vals[v]);
3363  perm[v] = v;
3364  }
3365 
3366  /* execute the sorting */
3367  SCIPsortDownRealInt(absvals, perm, lastbin);
3368 
3369  permSortConsdata(consdata, perm, lastbin);
3370 
3371  /* free temporary arrays */
3372  SCIPfreeBufferArray(scip, &perm);
3373  SCIPfreeBufferArray(scip, &absvals);
3374  }
3375  consdata->binvarssorted = TRUE;
3376 
3377  /* presolve sorting cannot be guaranteed after binary sorting */
3378  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3379  }
3380  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3381  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3382 
3383  return SCIP_OKAY;
3384 }
3385 
3386 
3387 /*
3388  * local linear constraint handler methods
3389  */
3390 
3391 /** sets left hand side of linear constraint */
3392 static
3394  SCIP* scip, /**< SCIP data structure */
3395  SCIP_CONS* cons, /**< linear constraint */
3396  SCIP_Real lhs /**< new left hand side */
3397  )
3398 {
3399  SCIP_CONSDATA* consdata;
3400 
3401  assert(scip != NULL);
3402  assert(cons != NULL);
3403  assert(!SCIPisInfinity(scip, lhs));
3404 
3405  /* adjust value to not be smaller than -inf */
3406  if ( SCIPisInfinity(scip, -lhs) )
3407  lhs = -SCIPinfinity(scip);
3408 
3409  consdata = SCIPconsGetData(cons);
3410  assert(consdata != NULL);
3411  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3412  assert(!SCIPisInfinity(scip, consdata->lhs));
3413 
3414  /* check whether the side is not changed */
3415  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3416  return SCIP_OKAY;
3417 
3418  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3419  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3420  {
3421  consdata->rhs = lhs;
3422  assert(consdata->row == NULL);
3423  }
3424 
3425  /* if necessary, update the rounding locks of variables */
3426  if( SCIPconsIsLocked(cons) )
3427  {
3428  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3429  {
3430  SCIP_VAR** vars;
3431  SCIP_Real* vals;
3432  int v;
3433 
3434  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3435  vars = consdata->vars;
3436  vals = consdata->vals;
3437 
3438  for( v = 0; v < consdata->nvars; ++v )
3439  {
3440  assert(vars[v] != NULL);
3441  assert(!SCIPisZero(scip, vals[v]));
3442 
3443  if( SCIPisPositive(scip, vals[v]) )
3444  {
3445  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3446  }
3447  else
3448  {
3449  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3450  }
3451  }
3452  }
3453  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3454  {
3455  SCIP_VAR** vars;
3456  SCIP_Real* vals;
3457  int v;
3458 
3459  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3460  vars = consdata->vars;
3461  vals = consdata->vals;
3462 
3463  for( v = 0; v < consdata->nvars; ++v )
3464  {
3465  assert(vars[v] != NULL);
3466  assert(!SCIPisZero(scip, vals[v]));
3467 
3468  if( SCIPisPositive(scip, vals[v]) )
3469  {
3470  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3471  }
3472  else
3473  {
3474  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3475  }
3476  }
3477  }
3478  }
3479 
3480  /* 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 */
3481  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3482  {
3483  consdata->boundstightened = 0;
3484  consdata->presolved = FALSE;
3485  consdata->cliquesadded = FALSE;
3486  consdata->implsadded = FALSE;
3487 
3488  /* mark the constraint for propagation */
3489  if( SCIPconsIsTransformed(cons) )
3490  {
3491  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3492  }
3493  }
3494 
3495  /* set new left hand side and update constraint data */
3496  consdata->lhs = lhs;
3497  consdata->changed = TRUE;
3498  consdata->normalized = FALSE;
3499  consdata->upgradetried = FALSE;
3500  consdata->rangedrowpropagated = 0;
3501 
3502 
3503  /* update the lhs of the LP row */
3504  if( consdata->row != NULL )
3505  {
3506  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3507  }
3508 
3509  return SCIP_OKAY;
3510 }
3511 
3512 /** sets right hand side of linear constraint */
3513 static
3515  SCIP* scip, /**< SCIP data structure */
3516  SCIP_CONS* cons, /**< linear constraint */
3517  SCIP_Real rhs /**< new right hand side */
3518  )
3519 {
3520  SCIP_CONSDATA* consdata;
3521 
3522  assert(scip != NULL);
3523  assert(cons != NULL);
3524  assert(!SCIPisInfinity(scip, -rhs));
3525 
3526  /* adjust value to not be larger than inf */
3527  if ( SCIPisInfinity(scip, rhs) )
3528  rhs = SCIPinfinity(scip);
3529 
3530  consdata = SCIPconsGetData(cons);
3531  assert(consdata != NULL);
3532  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3533  assert(!SCIPisInfinity(scip, -consdata->rhs));
3534 
3535  /* check whether the side is not changed */
3536  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3537  return SCIP_OKAY;
3538 
3539  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3540  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3541  {
3542  consdata->lhs = rhs;
3543  assert(consdata->row == NULL);
3544  }
3545 
3546  /* if necessary, update the rounding locks of variables */
3547  if( SCIPconsIsLocked(cons) )
3548  {
3549  assert(SCIPconsIsTransformed(cons));
3550 
3551  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3552  {
3553  SCIP_VAR** vars;
3554  SCIP_Real* vals;
3555  int v;
3556 
3557  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3558  vars = consdata->vars;
3559  vals = consdata->vals;
3560 
3561  for( v = 0; v < consdata->nvars; ++v )
3562  {
3563  assert(vars[v] != NULL);
3564  assert(!SCIPisZero(scip, vals[v]));
3565 
3566  if( SCIPisPositive(scip, vals[v]) )
3567  {
3568  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3569  }
3570  else
3571  {
3572  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3573  }
3574  }
3575  }
3576  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3577  {
3578  SCIP_VAR** vars;
3579  SCIP_Real* vals;
3580  int v;
3581 
3582  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3583  vars = consdata->vars;
3584  vals = consdata->vals;
3585 
3586  for( v = 0; v < consdata->nvars; ++v )
3587  {
3588  assert(vars[v] != NULL);
3589  assert(!SCIPisZero(scip, vals[v]));
3590 
3591  if( SCIPisPositive(scip, vals[v]) )
3592  {
3593  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3594  }
3595  else
3596  {
3597  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3598  }
3599  }
3600  }
3601  }
3602 
3603  /* 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 */
3604  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3605  {
3606  consdata->boundstightened = 0;
3607  consdata->presolved = FALSE;
3608  consdata->cliquesadded = FALSE;
3609  consdata->implsadded = FALSE;
3610 
3611  /* mark the constraint for propagation */
3612  if( SCIPconsIsTransformed(cons) )
3613  {
3614  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3615  }
3616  }
3617 
3618  /* set new right hand side and update constraint data */
3619  consdata->rhs = rhs;
3620  consdata->changed = TRUE;
3621  consdata->normalized = FALSE;
3622  consdata->upgradetried = FALSE;
3623  consdata->rangedrowpropagated = 0;
3624 
3625  /* update the rhs of the LP row */
3626  if( consdata->row != NULL )
3627  {
3628  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3629  }
3630 
3631  return SCIP_OKAY;
3632 }
3633 
3634 /** adds coefficient in linear constraint */
3635 static
3637  SCIP* scip, /**< SCIP data structure */
3638  SCIP_CONS* cons, /**< linear constraint */
3639  SCIP_VAR* var, /**< variable of constraint entry */
3640  SCIP_Real val /**< coefficient of constraint entry */
3641  )
3642 {
3643  SCIP_CONSDATA* consdata;
3644  SCIP_Bool transformed;
3645 
3646  assert(scip != NULL);
3647  assert(cons != NULL);
3648  assert(var != NULL);
3649 
3650  /* ignore coefficient if it is nearly zero */
3651  if( SCIPisZero(scip, val) )
3652  return SCIP_OKAY;
3654  consdata = SCIPconsGetData(cons);
3655  assert(consdata != NULL);
3656 
3657  /* are we in the transformed problem? */
3658  transformed = SCIPconsIsTransformed(cons);
3659 
3660  /* always use transformed variables in transformed constraints */
3661  if( transformed )
3662  {
3663  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3664  }
3665  assert(var != NULL);
3666  assert(transformed == SCIPvarIsTransformed(var));
3667 
3668  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3669  consdata->vars[consdata->nvars] = var;
3670  consdata->vals[consdata->nvars] = val;
3671  consdata->nvars++;
3672 
3673  /* capture variable */
3674  SCIP_CALL( SCIPcaptureVar(scip, var) );
3675 
3676  /* if we are in transformed problem, the variable needs an additional event data */
3677  if( transformed )
3678  {
3679  if( consdata->eventdata != NULL )
3680  {
3681  SCIP_CONSHDLR* conshdlr;
3682  SCIP_CONSHDLRDATA* conshdlrdata;
3683 
3684  /* check for event handler */
3685  conshdlr = SCIPconsGetHdlr(cons);
3686  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3687  assert(conshdlrdata != NULL);
3688  assert(conshdlrdata->eventhdlr != NULL);
3689 
3690  /* initialize eventdata array */
3691  consdata->eventdata[consdata->nvars-1] = NULL;
3692 
3693  /* catch bound change events of variable */
3694  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3695  }
3696 
3697  /* update minimum and maximum activities */
3698  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3699 
3700  /* update maximum activity delta */
3701  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3702  {
3703  SCIP_Real lb;
3704  SCIP_Real ub;
3705 
3706  lb = SCIPvarGetLbLocal(var);
3707  ub = SCIPvarGetUbLocal(var);
3708 
3709  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3710  {
3711  consdata->maxactdelta = SCIPinfinity(scip);
3712  consdata->maxactdeltavar = var;
3713  }
3714  else
3715  {
3716  SCIP_Real domain = ub - lb;
3717  SCIP_Real delta = REALABS(val) * domain;
3718 
3719  if( delta > consdata->maxactdelta )
3720  {
3721  consdata->maxactdelta = delta;
3722  consdata->maxactdeltavar = var;
3723  }
3724  }
3725  }
3726  }
3727 
3728  /* install rounding locks for new variable */
3729  SCIP_CALL( lockRounding(scip, cons, var, val) );
3730 
3731  /* mark the constraint for propagation */
3732  if( transformed )
3733  {
3734  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3735  }
3736 
3737  consdata->boundstightened = 0;
3738  consdata->presolved = FALSE;
3739  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3740 
3741  if( consdata->validsignature )
3742  consdataUpdateSignatures(consdata, consdata->nvars-1);
3743 
3744  consdata->changed = TRUE;
3745  consdata->normalized = FALSE;
3746  consdata->upgradetried = FALSE;
3747  consdata->cliquesadded = FALSE;
3748  consdata->implsadded = FALSE;
3749  consdata->rangedrowpropagated = 0;
3750 
3751  if( consdata->nvars == 1 )
3752  {
3753  consdata->binvarssorted = TRUE;
3754  consdata->sorted = TRUE;
3755  consdata->merged = TRUE;
3756  }
3757  else
3758  {
3759  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3760  consdata->sorted = consdata->sorted
3761  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3762  consdata->merged = FALSE;
3763  }
3764 
3765  /* update hascontvar and hasnonbinvar flags */
3766  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3767  {
3768  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3769 
3770  if( vartype != SCIP_VARTYPE_BINARY )
3771  {
3772  consdata->hasnonbinvar = TRUE;
3773 
3774  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3775  consdata->hascontvar = TRUE;
3776  }
3777  }
3778 
3779  /* add the new coefficient to the LP row */
3780  if( consdata->row != NULL )
3781  {
3782  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3783  }
3784 
3785  return SCIP_OKAY;
3786 }
3787 
3788 /** deletes coefficient at given position from linear constraint data */
3789 static
3791  SCIP* scip, /**< SCIP data structure */
3792  SCIP_CONS* cons, /**< linear constraint */
3793  int pos /**< position of coefficient to delete */
3794  )
3795 {
3796  SCIP_CONSDATA* consdata;
3797  SCIP_VAR* var;
3798  SCIP_Real val;
3799 
3800  assert(scip != NULL);
3801  assert(cons != NULL);
3802 
3803  consdata = SCIPconsGetData(cons);
3804  assert(consdata != NULL);
3805  assert(0 <= pos && pos < consdata->nvars);
3806 
3807  var = consdata->vars[pos];
3808  val = consdata->vals[pos];
3809  assert(var != NULL);
3810 
3811  /* remove rounding locks for deleted variable */
3812  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3813 
3814  /* if we are in transformed problem, delete the event data of the variable */
3815  if( SCIPconsIsTransformed(cons) )
3816  {
3817  SCIP_CONSHDLR* conshdlr;
3818  SCIP_CONSHDLRDATA* conshdlrdata;
3819 
3820  /* check for event handler */
3821  conshdlr = SCIPconsGetHdlr(cons);
3822  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3823  assert(conshdlrdata != NULL);
3824  assert(conshdlrdata->eventhdlr != NULL);
3825 
3826  /* drop bound change events of variable */
3827  if( consdata->eventdata != NULL )
3828  {
3829  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3830  assert(consdata->eventdata[pos] == NULL);
3831  }
3832  }
3833 
3834  /* move the last variable to the free slot */
3835  if( pos != consdata->nvars-1 )
3836  {
3837  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3838 
3839  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3840  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3841 
3842  if( consdata->eventdata != NULL )
3843  {
3844  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3845  assert(consdata->eventdata[pos] != NULL);
3846  consdata->eventdata[pos]->varpos = pos;
3847  }
3848  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3849  }
3850  consdata->nvars--;
3851 
3852  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3853  * of the remaining variable, or give exactly 0.0)
3854  */
3855  if( consdata->nvars <= 1 )
3856  consdataInvalidateActivities(consdata);
3857  else
3858  {
3859  if( SCIPconsIsTransformed(cons) )
3860  {
3861  /* if we are in transformed problem, update minimum and maximum activities */
3862  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3863 
3864  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3865  * delta needs to be recalculated on the next real propagation
3866  */
3867  if( consdata->maxactdeltavar == var )
3868  {
3869  consdata->maxactdelta = SCIP_INVALID;
3870  consdata->maxactdeltavar = NULL;
3871  }
3872  }
3873  }
3874 
3875  /* mark the constraint for propagation */
3876  if( SCIPconsIsTransformed(cons) )
3877  {
3878  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3879  }
3880 
3881  consdata->boundstightened = 0;
3882  consdata->presolved = FALSE;
3883  consdata->validsignature = FALSE;
3884  consdata->changed = TRUE;
3885  consdata->normalized = FALSE;
3886  consdata->upgradetried = FALSE;
3887  consdata->cliquesadded = FALSE;
3888  consdata->implsadded = FALSE;
3889  consdata->rangedrowpropagated = 0;
3890 
3891  /* check if hasnonbinvar flag might be incorrect now */
3892  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3893  {
3894  consdata->hasnonbinvalid = FALSE;
3895  }
3896 
3897  /* delete coefficient from the LP row */
3898  if( consdata->row != NULL )
3899  {
3900  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3901  }
3902 
3903  /* release variable */
3904  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3905 
3906  return SCIP_OKAY;
3907 }
3908 
3909 /** changes coefficient value at given position of linear constraint data */
3910 static
3912  SCIP* scip, /**< SCIP data structure */
3913  SCIP_CONS* cons, /**< linear constraint */
3914  int pos, /**< position of coefficient to delete */
3915  SCIP_Real newval /**< new value of coefficient */
3916  )
3917 {
3918  SCIP_CONSDATA* consdata;
3919  SCIP_VAR* var;
3920  SCIP_Real val;
3921 
3922  assert(scip != NULL);
3923  assert(cons != NULL);
3924  assert(!SCIPisZero(scip, newval));
3925 
3926  consdata = SCIPconsGetData(cons);
3927  assert(consdata != NULL);
3928  assert(0 <= pos && pos < consdata->nvars);
3929  assert(!SCIPisZero(scip, newval));
3930 
3931  var = consdata->vars[pos];
3932  val = consdata->vals[pos];
3933  assert(var != NULL);
3934  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3935 
3936  /* if necessary, update the rounding locks of the variable */
3937  if( SCIPconsIsLocked(cons) && newval * val < 0.0 )
3938  {
3939  assert(SCIPconsIsTransformed(cons));
3940 
3941  /* remove rounding locks for variable with old coefficient */
3942  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3943 
3944  /* install rounding locks for variable with new coefficient */
3945  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3946  }
3947 
3948  /* change the value */
3949  consdata->vals[pos] = newval;
3950 
3951  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3952 
3953  /* update minimum and maximum activities */
3954  if( SCIPconsIsTransformed(cons) )
3955  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3956 
3957  /* mark the constraint for propagation */
3958  if( SCIPconsIsTransformed(cons) )
3959  {
3960  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3961  }
3962 
3963  consdata->boundstightened = 0;
3964  consdata->presolved = FALSE;
3965  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3966  consdata->changed = TRUE;
3967  consdata->normalized = FALSE;
3968  consdata->upgradetried = FALSE;
3969  consdata->cliquesadded = FALSE;
3970  consdata->implsadded = FALSE;
3971  consdata->rangedrowpropagated = 0;
3972 
3973  return SCIP_OKAY;
3974 }
3975 
3976 /** scales a linear constraint with a constant scalar */
3977 static
3979  SCIP* scip, /**< SCIP data structure */
3980  SCIP_CONS* cons, /**< linear constraint to scale */
3981  SCIP_Real scalar /**< value to scale constraint with */
3982  )
3983 {
3984  SCIP_CONSDATA* consdata;
3985  SCIP_Real newval;
3986  SCIP_Real absscalar;
3987  int i;
3988 
3989  assert(scip != NULL);
3990  assert(cons != NULL);
3991 
3992  consdata = SCIPconsGetData(cons);
3993  assert(consdata != NULL);
3994  assert(consdata->row == NULL);
3995  assert(!SCIPisEQ(scip, scalar, 1.0));
3996 
3997  /* scale the coefficients */
3998  for( i = consdata->nvars - 1; i >= 0; --i )
3999  {
4000  newval = scalar * consdata->vals[i];
4001 
4002  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4003  * flooring down our new value
4004  */
4005  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4006  newval = SCIPfeasFloor(scip, newval + 0.5);
4007 
4008  if( SCIPisZero(scip, newval) )
4009  {
4010  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4011  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4012  SCIP_CALL( delCoefPos(scip, cons, i) );
4013  }
4014  else
4015  consdata->vals[i] = newval;
4016  }
4017 
4018  /* scale the sides */
4019  if( scalar < 0.0 )
4020  {
4021  SCIP_Real lhs;
4022 
4023  lhs = consdata->lhs;
4024  consdata->lhs = -consdata->rhs;
4025  consdata->rhs = -lhs;
4026  }
4027  absscalar = REALABS(scalar);
4028  if( !SCIPisInfinity(scip, -consdata->lhs) )
4029  {
4030  newval = absscalar * consdata->lhs;
4031 
4032  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4033  * flooring down our new value
4034  */
4035  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4036  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4037  else
4038  consdata->lhs = newval;
4039  }
4040  if( !SCIPisInfinity(scip, consdata->rhs) )
4041  {
4042  newval = absscalar * consdata->rhs;
4043 
4044  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4045  * our new value
4046  */
4047  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4048  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4049  else
4050  consdata->rhs = newval;
4051  }
4052 
4053  consdataInvalidateActivities(consdata);
4054  consdata->cliquesadded = FALSE;
4055  consdata->implsadded = FALSE;
4056 
4057  return SCIP_OKAY;
4058 }
4059 
4060 /* perform deletion of variables in all constraints of the constraint handler */
4061 static
4063  SCIP* scip, /**< SCIP data structure */
4064  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4065  SCIP_CONS** conss, /**< array of constraints */
4066  int nconss /**< number of constraints */
4067  )
4068 {
4069  SCIP_CONSDATA* consdata;
4070  int i;
4071  int v;
4072 
4073  assert(scip != NULL);
4074  assert(conshdlr != NULL);
4075  assert(conss != NULL);
4076  assert(nconss >= 0);
4077  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4078 
4079  /* iterate over all constraints */
4080  for( i = 0; i < nconss; i++ )
4081  {
4082  consdata = SCIPconsGetData(conss[i]);
4083 
4084  /* constraint is marked, that some of its variables were deleted */
4085  if( consdata->varsdeleted )
4086  {
4087  /* iterate over all variables of the constraint and delete them from the constraint */
4088  for( v = consdata->nvars - 1; v >= 0; --v )
4089  {
4090  if( SCIPvarIsDeleted(consdata->vars[v]) )
4091  {
4092  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4093  }
4094  }
4095  consdata->varsdeleted = FALSE;
4096  }
4097  }
4098 
4099  return SCIP_OKAY;
4100 }
4101 
4102 
4103 /** normalizes a linear constraint with the following rules:
4104  * - if all coefficients have them same absolute value, change them to (-)1.0
4105  * - multiplication with +1 or -1:
4106  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4107  * if the current rule doesn't determine the sign):
4108  * 1. the right hand side must not be negative
4109  * 2. the right hand side must not be infinite
4110  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4111  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4112  * 5. multiply with +1
4113  * - rationals to integrals
4114  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4115  * by the smallest common multiple of all denominators to get integral coefficients.
4116  * Forbid large denominators due to numerical stability.
4117  * - division by greatest common divisor
4118  * If all coefficients are integral, divide them by the greatest common divisor.
4119  */
4120 static
4122  SCIP* scip, /**< SCIP data structure */
4123  SCIP_CONS* cons /**< linear constraint to normalize */
4124  )
4125 {
4126  SCIP_CONSDATA* consdata;
4127  SCIP_VAR** vars;
4128  SCIP_Real* vals;
4129  SCIP_Longint scm;
4130  SCIP_Longint nominator;
4131  SCIP_Longint denominator;
4132  SCIP_Longint gcd;
4133  SCIP_Longint maxmult;
4134  SCIP_Real epsilon;
4135  SCIP_Real feastol;
4136  SCIP_Real maxabsval;
4137  SCIP_Real minabsval;
4138  SCIP_Bool success;
4139  SCIP_Bool onlyintegral;
4140  int nvars;
4141  int mult;
4142  int nposcoeffs;
4143  int nnegcoeffs;
4144  int i;
4145  int v;
4146 
4147  assert(scip != NULL);
4148  assert(cons != NULL);
4149 
4150  /* we must not change a modifiable constraint in any way */
4151  if( SCIPconsIsModifiable(cons) )
4152  return SCIP_OKAY;
4153 
4154  /* get constraint data */
4155  consdata = SCIPconsGetData(cons);
4156  assert(consdata != NULL);
4157 
4158  /* check, if the constraint is already normalized */
4159  if( consdata->normalized )
4160  return SCIP_OKAY;
4161 
4162  /* get coefficient arrays */
4163  vals = consdata->vals;
4164  nvars = consdata->nvars;
4165  vars = consdata->vars;
4166  assert(nvars == 0 || vars != NULL);
4167  assert(nvars == 0 || vals != NULL);
4168 
4169  if( nvars == 0 )
4170  {
4171  consdata->normalized = TRUE;
4172  return SCIP_OKAY;
4173  }
4174 
4175  assert(vars != NULL);
4176  assert(vals != NULL);
4177 
4178  /* get maximal and minimal absolute coefficient */
4179  maxabsval = consdataGetMaxAbsval(consdata);
4180  minabsval = consdataGetMinAbsval(consdata);
4181 
4182  /* return if scaling by maxval will eliminate coefficients */
4183  if( SCIPisZero(scip, minabsval/maxabsval) )
4184  return SCIP_OKAY;
4185 
4186  /* check if all coefficients are in absolute value equal, and not 1.0 */
4187  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4188  {
4189  SCIP_Bool abscoefsequ;
4190 
4191  abscoefsequ = TRUE;
4192 
4193  for( v = nvars - 1; v >= 0; --v )
4194  {
4195  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4196  {
4197  abscoefsequ = FALSE;
4198  break;
4199  }
4200  }
4201 
4202  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4203  if( abscoefsequ )
4204  {
4205  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficents are in absolute value the same\n", maxabsval);
4206  SCIPdebugPrintCons(scip, cons, NULL);
4207  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4208 
4209  if( consdata->validmaxabsval )
4210  {
4211  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4212  consdata->maxabsval = 1.0;
4213  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4214  consdata->minabsval = 1.0;
4215 
4216  maxabsval = 1.0;
4217  }
4218  else
4219  {
4220  /* get maximal absolute coefficient */
4221  maxabsval = consdataGetMaxAbsval(consdata);
4222  }
4223 
4224  /* get new consdata information, because scalecons() might have deleted variables */
4225  vals = consdata->vals;
4226  nvars = consdata->nvars;
4227  vars = consdata->vars;
4228 
4229  assert(nvars == 0 || vars != NULL);
4230  assert(nvars == 0 || vals != NULL);
4231  }
4232  }
4233 
4234  /* nvars might have changed */
4235  if( nvars == 0 )
4236  {
4237  consdata->normalized = TRUE;
4238  return SCIP_OKAY;
4239  }
4240 
4241  assert(vars != NULL);
4242  assert(vals != NULL);
4243 
4244  /* calculate the maximal multiplier for common divisor calculation:
4245  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4246  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4247  * additionally, we don't want to scale the constraint if this would lead to too
4248  * large coefficients
4249  */
4250  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4251  feastol = SCIPfeastol(scip);
4252  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4253  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
4254 
4255  if( !consdata->hasnonbinvalid )
4256  consdataCheckNonbinvar(consdata);
4257 
4258  /* if all variables are of integral type we will allow a greater multiplier */
4259  if( !consdata->hascontvar )
4260  {
4261  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
4262  {
4263  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4264  }
4265  }
4266  else
4267  {
4268  SCIP_Bool foundcont;
4269 
4270  foundcont = FALSE;
4271 
4272  for( v = nvars - 1; v >= 0; --v )
4273  {
4274  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4275  {
4276  foundcont = TRUE;
4277  break;
4278  }
4279  }
4280 
4281  if( !foundcont )
4282  {
4283  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4284  }
4285  }
4286 
4287  /*
4288  * multiplication with +1 or -1
4289  */
4290  mult = 0;
4291 
4292  /* 1. the right hand side must not be negative */
4293  if( SCIPisPositive(scip, consdata->lhs) )
4294  mult = +1;
4295  else if( SCIPisNegative(scip, consdata->rhs) )
4296  mult = -1;
4297 
4298  if( mult == 0 )
4299  {
4300  /* 2. the right hand side must not be infinite */
4301  if( SCIPisInfinity(scip, -consdata->lhs) )
4302  mult = +1;
4303  else if( SCIPisInfinity(scip, consdata->rhs) )
4304  mult = -1;
4305  }
4306 
4307  if( mult == 0 )
4308  {
4309  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4310  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4311  mult = +1;
4312  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4313  mult = -1;
4314  }
4315 
4316  if( mult == 0 )
4317  {
4318  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4319  nposcoeffs = 0;
4320  nnegcoeffs = 0;
4321  for( i = 0; i < nvars; ++i )
4322  {
4323  if( vals[i] > 0.0 )
4324  nposcoeffs++;
4325  else
4326  nnegcoeffs++;
4327  }
4328  if( nposcoeffs > nnegcoeffs )
4329  mult = +1;
4330  else if( nposcoeffs < nnegcoeffs )
4331  mult = -1;
4332  }
4333 
4334  if( mult == 0 )
4335  {
4336  /* 5. multiply with +1 */
4337  mult = +1;
4338  }
4339 
4340  assert(mult == +1 || mult == -1);
4341  if( mult == -1 )
4342  {
4343  /* scale the constraint with -1 */
4344  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4345  SCIPdebugPrintCons(scip, cons, NULL);
4346  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4347 
4348  /* scalecons() can delete variables, but scaling with -1 should not do that */
4349  assert(nvars == consdata->nvars);
4350  }
4351 
4352  /*
4353  * rationals to integrals
4354  *
4355  * @todo try scaling only on behalf of non-continuous variables
4356  */
4357  success = TRUE;
4358  scm = 1;
4359  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4360  {
4361  if( !SCIPisIntegral(scip, vals[i]) )
4362  {
4363  /* epsilon has been slightly decreased above - to be on the safe side */
4364  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4365  if( success )
4366  scm = SCIPcalcSmaComMul(scm, denominator);
4367  }
4368  }
4369  assert(scm >= 1);
4370 
4371  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4372  * their greatest common divisor
4373  */
4374  onlyintegral = TRUE;
4375  if( scm == 1 )
4376  {
4377  for( i = nvars - 1; i >= 0; --i )
4378  {
4379  if( !SCIPisIntegral(scip, vals[i]) )
4380  {
4381  onlyintegral = FALSE;
4382  break;
4383  }
4384  }
4385  }
4386 
4387  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4388  if( success && scm != 1 )
4389  {
4390  /* scale the constraint with the smallest common multiple of all denominators */
4391  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4392  SCIPdebugPrintCons(scip, cons, NULL);
4393  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4394 
4395  if( consdata->validmaxabsval )
4396  {
4397  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4398  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4399  {
4400  consdata->validmaxabsval = FALSE;
4401  consdata->maxabsval = SCIP_INVALID;
4402  consdataCalcMaxAbsval(consdata);
4403  }
4404  }
4405 
4406  if( consdata->validminabsval )
4407  {
4408  consdata->minabsval *= REALABS((SCIP_Real)scm);
4409  if( !SCIPisIntegral(scip, consdata->minabsval) )
4410  {
4411  consdata->validminabsval = FALSE;
4412  consdata->minabsval = SCIP_INVALID;
4413  consdataCalcMinAbsval(consdata);
4414  }
4415  }
4416 
4417  /* get new consdata information, because scalecons() might have deleted variables */
4418  vals = consdata->vals;
4419  nvars = consdata->nvars;
4420  assert(nvars == 0 || vals != NULL);
4421  }
4422 
4423  /*
4424  * division by greatest common divisor
4425  */
4426  if( success && nvars >= 1 )
4427  {
4428  /* all coefficients are integral: divide them by their greatest common divisor */
4429  assert(SCIPisIntegral(scip, vals[0]));
4430 
4431  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4432  for( i = 1; i < nvars && gcd > 1; ++i )
4433  {
4434  assert(SCIPisIntegral(scip, vals[i]));
4435  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4436  }
4437 
4438  if( gcd > 1 )
4439  {
4440  /* divide the constraint by the greatest common divisor of the coefficients */
4441  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4442  SCIPdebugPrintCons(scip, cons, NULL);
4443  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4444 
4445  if( consdata->validmaxabsval )
4446  {
4447  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4448  }
4449  if( consdata->validminabsval )
4450  {
4451  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4452  }
4453  }
4454  }
4455 
4456  /* mark constraint to be normalized */
4457  consdata->normalized = TRUE;
4458 
4459  SCIPdebugMsg(scip, "normalized constraint:\n");
4460  SCIPdebugPrintCons(scip, cons, NULL);
4461 
4462  return SCIP_OKAY;
4463 }
4464 
4465 /** replaces multiple occurrences of a variable by a single coefficient */
4466 static
4468  SCIP* scip, /**< SCIP data structure */
4469  SCIP_CONS* cons /**< linear constraint */
4470  )
4471 {
4472  SCIP_CONSDATA* consdata;
4473  SCIP_VAR* var;
4474  SCIP_Real valsum;
4475  int v;
4476 
4477  assert(scip != NULL);
4478  assert(cons != NULL);
4479 
4480  consdata = SCIPconsGetData(cons);
4481  assert(consdata != NULL);
4482 
4483  if( consdata->merged )
4484  return SCIP_OKAY;
4485 
4486  /* sort the constraint */
4487  SCIP_CALL( consdataSort(scip, consdata) );
4488 
4489  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4490  * backward direction is necessary, since delCoefPos() modifies the given position and
4491  * the subsequent ones
4492  */
4493  v = consdata->nvars-1;
4494  while( v >= 1 )
4495  {
4496  var = consdata->vars[v];
4497  if( consdata->vars[v-1] == var )
4498  {
4499  valsum = consdata->vals[v];
4500  do
4501  {
4502  SCIP_CALL( delCoefPos(scip, cons, v) );
4503  --v;
4504  valsum += consdata->vals[v];
4505  }
4506  while( v >= 1 && consdata->vars[v-1] == var );
4507 
4508  /* modify the last existing occurrence of the variable */
4509  assert(consdata->vars[v] == var);
4510  if( SCIPisZero(scip, valsum) )
4511  {
4512  SCIP_CALL( delCoefPos(scip, cons, v) );
4513 
4514  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4515  * delta needs to be recalculated on the next real propagation
4516  */
4517  if( consdata->maxactdeltavar == var )
4518  {
4519  consdata->maxactdelta = SCIP_INVALID;
4520  consdata->maxactdeltavar = NULL;
4521  }
4522  }
4523  else
4524  {
4525  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4526  }
4527  }
4528  --v;
4529  }
4530 
4531  consdata->merged = TRUE;
4532 
4533  return SCIP_OKAY;
4534 }
4535 
4536 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4537 static
4539  SCIP* scip, /**< SCIP data structure */
4540  SCIP_CONS* cons, /**< linear constraint */
4541  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4542  * information is not needed; in this case, we apply all fixings
4543  * instead of stopping after the first infeasible one */
4544  )
4545 {
4546  SCIP_CONSDATA* consdata;
4547  SCIP_VAR* var;
4548  SCIP_VAR** aggrvars;
4549  SCIP_Real val;
4550  SCIP_Real* aggrscalars;
4551  SCIP_Real fixedval;
4552  SCIP_Real aggrconst;
4553  int v;
4554  int naggrvars;
4555  int i;
4556 
4557  assert(scip != NULL);
4558  assert(cons != NULL);
4559 
4560  if( infeasible != NULL )
4561  *infeasible = FALSE;
4562 
4563  consdata = SCIPconsGetData(cons);
4564  assert(consdata != NULL);
4565 
4566  if( !consdata->removedfixings )
4567  {
4568  SCIP_Real lhssubtrahend;
4569  SCIP_Real rhssubtrahend;
4570 
4571  lhssubtrahend = 0.0;
4572  rhssubtrahend = 0.0;
4573 
4574  SCIPdebugMsg(scip, "applying fixings:\n");
4575  SCIPdebugPrintCons(scip, cons, NULL);
4576 
4577  v = 0;
4578  while( v < consdata->nvars )
4579  {
4580  var = consdata->vars[v];
4581  val = consdata->vals[v];
4582  assert(SCIPvarIsTransformed(var));
4583 
4584  switch( SCIPvarGetStatus(var) )
4585  {
4587  SCIPerrorMessage("original variable in transformed linear constraint\n");
4588  return SCIP_INVALIDDATA;
4589 
4590  case SCIP_VARSTATUS_LOOSE:
4591  case SCIP_VARSTATUS_COLUMN:
4592  ++v;
4593  break;
4594 
4595  case SCIP_VARSTATUS_FIXED:
4596  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4597  fixedval = SCIPvarGetLbGlobal(var);
4598  if( !SCIPisInfinity(scip, -consdata->lhs) )
4599  {
4600  if( SCIPisInfinity(scip, ABS(fixedval)) )
4601  {
4602  if( val * fixedval > 0.0 )
4603  {
4604  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4605  }
4606  else
4607  {
4608  if( infeasible != NULL )
4609  {
4610  /* if lhs gets infinity it means that the problem is infeasible */
4611  *infeasible = TRUE;
4612  return SCIP_OKAY;
4613  }
4614  else
4615  {
4616  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4617  }
4618  }
4619  }
4620  else
4621  lhssubtrahend += val * fixedval;
4622  }
4623  if( !SCIPisInfinity(scip, consdata->rhs) )
4624  {
4625  if( SCIPisInfinity(scip, ABS(fixedval)) )
4626  {
4627  if( val * fixedval > 0.0 )
4628  {
4629  if( infeasible != NULL )
4630  {
4631  /* if rhs gets -infinity it means that the problem is infeasible */
4632  *infeasible = TRUE;
4633  return SCIP_OKAY;
4634  }
4635  else
4636  {
4637  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4638  }
4639  }
4640  else
4641  {
4642  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4643  }
4644  }
4645  else
4646  rhssubtrahend += val * fixedval;
4647  }
4648  SCIP_CALL( delCoefPos(scip, cons, v) );
4649  break;
4650 
4652  {
4653  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4654  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4655  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4656 
4657  assert(activevar != NULL);
4658  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4659  assert(activevar != NULL);
4660 
4661  if( !SCIPisZero(scip, activescalar) )
4662  {
4663  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4664  }
4665 
4666  if( !SCIPisZero(scip, activeconstant) )
4667  {
4668  if( !SCIPisInfinity(scip, -consdata->lhs) )
4669  lhssubtrahend += activeconstant;
4670  if( !SCIPisInfinity(scip, consdata->rhs) )
4671  rhssubtrahend += activeconstant;
4672  }
4673 
4674  SCIP_CALL( delCoefPos(scip, cons, v) );
4675  break;
4676  }
4679  naggrvars = SCIPvarGetMultaggrNVars(var);
4680  aggrvars = SCIPvarGetMultaggrVars(var);
4681  aggrscalars = SCIPvarGetMultaggrScalars(var);
4682  for( i = 0; i < naggrvars; ++i )
4683  {
4684  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4685  }
4686  aggrconst = SCIPvarGetMultaggrConstant(var);
4687 
4688  if( !SCIPisInfinity(scip, -consdata->lhs) )
4689  lhssubtrahend += val * aggrconst;
4690  if( !SCIPisInfinity(scip, consdata->rhs) )
4691  rhssubtrahend += val * aggrconst;
4692 
4693  SCIP_CALL( delCoefPos(scip, cons, v) );
4694  break;
4695 
4697  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4698  aggrconst = SCIPvarGetNegationConstant(var);
4699 
4700  if( !SCIPisInfinity(scip, -consdata->lhs) )
4701  lhssubtrahend += val * aggrconst;
4702  if( !SCIPisInfinity(scip, consdata->rhs) )
4703  rhssubtrahend += val * aggrconst;
4704 
4705  SCIP_CALL( delCoefPos(scip, cons, v) );
4706  break;
4707 
4708  default:
4709  SCIPerrorMessage("unknown variable status\n");
4710  SCIPABORT();
4711  return SCIP_INVALIDDATA; /*lint !e527*/
4712  }
4713  }
4714 
4715  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4716  {
4717  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4718  * causing wrong fixings of other variables --> better use a real zero here;
4719  * for small numbers, polishing the difference might lead to wrong results -->
4720  * better use the exact difference in this case
4721  */
4722  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4723  {
4724  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4725  }
4726  else
4727  {
4728  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4729  }
4730  }
4731  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4732  {
4733 
4734  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4735  * causing wrong fixings of other variables --> better use a real zero here;
4736  * for small numbers, polishing the difference might lead to wrong results -->
4737  * better use the exact difference in this case
4738  */
4739  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4740  {
4741  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4742  }
4743  else
4744  {
4745  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4746  }
4747  }
4748 
4749  consdata->removedfixings = TRUE;
4750 
4751  SCIPdebugMsg(scip, "after fixings:\n");
4752  SCIPdebugPrintCons(scip, cons, NULL);
4753 
4754  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4755  * to clean up the constraint
4756  */
4757  SCIP_CALL( mergeMultiples(scip, cons) );
4758 
4759  SCIPdebugMsg(scip, "after merging:\n");
4760  SCIPdebugPrintCons(scip, cons, NULL);
4761  }
4762  assert(consdata->removedfixings);
4763 
4764 #ifndef NDEBUG
4765  /* check, if all fixings are applied */
4766  for( v = 0; v < consdata->nvars; ++v )
4767  assert(SCIPvarIsActive(consdata->vars[v]));
4768 #endif
4769 
4770  return SCIP_OKAY;
4771 }
4772 
4773 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4774  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4775  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4776  * conflict detecting constraint by using NULL as inferred variable
4777  */
4778 static
4780  SCIP* scip, /**< SCIP data structure */
4781  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4782  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4783  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4784  int inferpos, /**< position of the inferred variable in the vars array */
4785  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4786  )
4787 {
4788  SCIP_CONSDATA* consdata;
4789  SCIP_VAR** vars;
4790  SCIP_Real* vals;
4791  int nvars;
4792  int i;
4793 
4794  assert(scip != NULL);
4795  assert(cons != NULL);
4797  consdata = SCIPconsGetData(cons);
4798 
4799  assert(consdata != NULL);
4800 
4801  vars = consdata->vars;
4802  vals = consdata->vals;
4803  nvars = consdata->nvars;
4804 
4805  assert(vars != NULL || nvars == 0);
4806  assert(vals != NULL || nvars == 0);
4807 
4808  assert(-1 <= inferpos && inferpos < nvars);
4809  assert((infervar == NULL) == (inferpos == -1));
4810  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4811 
4812  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4813  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4814  * - if the right hand side is the reason, the minimal residual activity is responsible
4815  * - if the left hand side is the reason, the maximal residual activity is responsible
4816  */
4817 
4818  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4819  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4820  {
4821  SCIP_Real minresactivity;
4822  SCIP_Real maxresactivity;
4823  SCIP_Bool minisrelax;
4824  SCIP_Bool maxisrelax;
4825  SCIP_Bool isminsettoinfinity;
4826  SCIP_Bool ismaxsettoinfinity;
4827 
4828  minresactivity = -SCIPinfinity(scip);
4829  maxresactivity = SCIPinfinity(scip);
4830 
4831  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4832  if( infervar != NULL )
4833  {
4834  assert(vals != NULL); /* for flexelint */
4835  if( reasonisrhs )
4836  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4837  &minisrelax, NULL, &isminsettoinfinity, NULL);
4838  else
4839  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4840  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4841  }
4842  else
4843  {
4844  if( reasonisrhs )
4845  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4846  &minisrelax, NULL, &isminsettoinfinity, NULL);
4847  else
4848  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4849  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4850  }
4851 
4852  /* we can only do something clever, if the residual activity is finite and not relaxed */
4853  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4854  {
4855  SCIP_Real rescap;
4856  SCIP_Bool resactisinf;
4857 
4858  resactisinf = FALSE;
4859 
4860  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4861  * than its inferred bound
4862  */
4863  if( infervar != NULL )
4864  {
4865  assert(vals != NULL); /* for flexelint */
4866 
4867  if( reasonisrhs )
4868  {
4869  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4870  {
4871  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4872  if( SCIPisInfinity(scip, -minresactivity) )
4873  resactisinf = TRUE;
4874  }
4875  rescap = consdata->rhs - minresactivity;
4876  }
4877  else
4878  {
4879  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4880  {
4881  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4882  if( SCIPisInfinity(scip, maxresactivity) )
4883  resactisinf = TRUE;
4884  }
4885  rescap = consdata->lhs - maxresactivity;
4886  }
4887 
4888  if( reasonisrhs == (vals[inferpos] > 0.0) )
4889  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4890  else
4891  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4892  }
4893  else
4894  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4895 
4896  if( !resactisinf )
4897  {
4898  /* now add bounds as reasons until the residual capacity is exceeded */
4899  for( i = 0; i < nvars; ++i )
4900  {
4901  assert( vars != NULL && vals != NULL ); /* for lint */
4902 
4903  /* zero coefficients and the infered variable can be ignored */
4904  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4905  continue;
4906 
4907  /* check if the residual capacity is exceeded */
4908  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4909  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4910  break;
4911 
4912  /* update the residual capacity due to the local bound of this variable */
4913  if( reasonisrhs == (vals[i] > 0.0) )
4914  {
4915  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4916  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4917  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4918  }
4919  else
4920  {
4921  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4922  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4923  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4924  }
4925  }
4926  return SCIP_OKAY;
4927  }
4928  }
4929  }
4930 
4931  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4932  for( i = 0; i < nvars; ++i )
4933  {
4934  assert(vars != NULL); /* for flexelint */
4935  assert(vals != NULL); /* for flexelint */
4936 
4937  /* zero coefficients and the infered variable can be ignored */
4938  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4939  continue;
4940 
4941  if( reasonisrhs == (vals[i] > 0.0) )
4942  {
4943  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4944  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4945  }
4946  else
4947  {
4948  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4949  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4950  }
4951  }
4952 
4953  return SCIP_OKAY;
4954 }
4955 
4956 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4957  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4958  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4959  */
4960 static
4962  SCIP* scip, /**< SCIP data structure */
4963  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4964  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4965  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4966  int inferpos /**< position of the inferred variable in the vars array, or -1 */
4967  )
4968 {
4969  SCIP_CONSDATA* consdata;
4970  SCIP_VAR** vars;
4971  int nvars;
4972  int v;
4973 
4974  assert(scip != NULL);
4975  assert(cons != NULL);
4976 
4977  consdata = SCIPconsGetData(cons);
4978  assert(consdata != NULL);
4979  vars = consdata->vars;
4980  nvars = consdata->nvars;
4981  assert(vars != NULL || nvars == 0);
4982  assert(-1 <= inferpos && inferpos < nvars);
4983  assert((infervar == NULL) == (inferpos == -1));
4984  assert(inferpos == -1 || vars != NULL);
4985  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4986 
4987  /* collect all fixed variables */
4988  for( v = nvars - 1; v >= 0; --v )
4989  {
4990  assert(vars != NULL); /* for flexelint */
4991 
4992  /* need to add old bounds before propagation of inferrence variable */
4993  if( vars[v] == infervar )
4994  {
4995  assert(vars[v] != NULL);
4996 
4997  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
4998  {
4999  /* @todo get boundchange index before this last boundchange and correct the index */
5000  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5001  }
5002 
5003  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5004  {
5005  /* @todo get boundchange index before this last boundchange and correct the index */
5006  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5007  }
5008 
5009  continue;
5010  }
5011 
5012  /* check for fixed variables */
5013  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5014  {
5015  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5016  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5017  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5018  }
5019  }
5020 
5021  return SCIP_OKAY;
5022 }
5023 
5024 /** add reasoning variables to conflict candidate queue which led to the conflict */
5025 static
5027  SCIP* scip, /**< SCIP data structure */
5028  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5029  int nvars, /**< number of variables reasoning the infeasibility */
5030  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5031  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5032  )
5033 {
5034  int v;
5035 
5036  assert(scip != NULL);
5037 
5038  /* collect all variables for which the local bounds differ from their global bounds */
5039  for( v = nvars - 1; v >= 0; --v )
5040  {
5041  assert(vars != NULL);
5042 
5043  /* check for local bound changes variables */
5044  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5045  {
5046  /* add conflict bound */
5047  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5048  }
5049 
5050  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5051  {
5052  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5053  }
5054  }
5055 
5056  if( var != NULL )
5057  {
5058  if( bound < SCIPvarGetLbLocal(var) )
5059  {
5060  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5061  }
5062 
5063  if( bound > SCIPvarGetUbLocal(var) )
5064  {
5065  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5066  }
5067  }
5068 
5069  return SCIP_OKAY;
5070 }
5071 
5072 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5073  * propagation rule (see propagateCons()):
5074  * (1) activity residuals of all other variables tighten bounds of single variable
5075  */
5076 static
5078  SCIP* scip, /**< SCIP data structure */
5079  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5080  SCIP_VAR* infervar, /**< variable that was deduced */
5081  INFERINFO inferinfo, /**< inference information */
5082  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5083  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5084  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5085  )
5086 {
5087  SCIP_CONSDATA* consdata;
5088  SCIP_VAR** vars;
5089 #ifndef NDEBUG
5090  SCIP_Real* vals;
5091 #endif
5092  int nvars;
5093  int inferpos;
5095  assert(scip != NULL);
5096  assert(cons != NULL);
5097  assert(result != NULL);
5098 
5099  consdata = SCIPconsGetData(cons);
5100  assert(consdata != NULL);
5101  vars = consdata->vars;
5102  nvars = consdata->nvars;
5103 #ifndef NDEBUG
5104  vals = consdata->vals;
5105  assert(vars != NULL);
5106  assert(vals != NULL);
5107 #endif
5108 
5109  /* get the position of the inferred variable in the vars array */
5110  inferpos = inferInfoGetPos(inferinfo);
5111  if( inferpos >= nvars || vars[inferpos] != infervar )
5112  {
5113  /* find inference variable in constraint */
5114  /**@todo use a binary search here; the variables can be sorted by variable index */
5115  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5116  {}
5117  }
5118  assert(inferpos < nvars);
5119  assert(vars[inferpos] == infervar);
5120  assert(!SCIPisZero(scip, vals[inferpos]));
5121 
5122  switch( inferInfoGetProprule(inferinfo) )
5123  {
5124  case PROPRULE_1_RHS:
5125  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5126  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5127  * domain in order to not exceed the right hand side of the inequality
5128  */
5129  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5130  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5131  *result = SCIP_SUCCESS;
5132  break;
5133 
5134  case PROPRULE_1_LHS:
5135  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5136  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5137  * domain in order to not fall below the left hand side of the inequality
5138  */
5139  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5140  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5141  *result = SCIP_SUCCESS;
5142  break;
5143 
5144  case PROPRULE_1_RANGEDROW:
5145  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5146  * the given inference variable to their bounds in this given ranged row
5147  */
5148 
5149  /* check that we really have a ranged row here */
5150  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5151  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5152  *result = SCIP_SUCCESS;
5153  break;
5154 
5155  case PROPRULE_INVALID:
5156  default:
5157  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5158  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5159  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5160  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5161  SCIPinfoMessage(scip, NULL, ";\n");
5162  return SCIP_INVALIDDATA;
5163  }
5164 
5165  return SCIP_OKAY;
5166 }
5167 
5168 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5169 static
5171  SCIP* scip, /**< SCIP data structure */
5172  SCIP_CONS* cons, /**< conflict detecting constraint */
5173  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5174  )
5175 {
5176  /* conflict analysis can only be applied in solving stage and if it is turned on */
5178  return SCIP_OKAY;
5179 
5180  /* initialize conflict analysis */
5182 
5183  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5184  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5185 
5186  /* analyze the conflict */
5187  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5188 
5189  return SCIP_OKAY;
5190 }
5191 
5192 /** check if there is any hope of tightening some bounds */
5193 static
5195  SCIP* scip, /**< SCIP data structure */
5196  SCIP_CONS* cons /**< linear constraint */
5197  )
5198 {
5199  SCIP_CONSDATA* consdata;
5200  int infcountmin;
5201  int infcountmax;
5202 
5203  consdata = SCIPconsGetData(cons);
5204  assert(consdata != NULL);
5205 
5206  infcountmin = consdata->minactivityneginf
5207  + consdata->minactivityposinf
5208  + consdata->minactivityneghuge
5209  + consdata->minactivityposhuge;
5210  infcountmax = consdata->maxactivityneginf
5211  + consdata->maxactivityposinf
5212  + consdata->maxactivityneghuge
5213  + consdata->maxactivityposhuge;
5214 
5215  if( infcountmin > 1 && infcountmax > 1 )
5216  return FALSE;
5217 
5218  return TRUE;
5219 }
5220 
5221 /** tighten upper bound */
5222 static
5224  SCIP* scip, /**< SCIP data structure */
5225  SCIP_CONS* cons, /**< linear constraint */
5226  int pos, /**< variable position */
5227  PROPRULE proprule, /**< propagation rule that deduced the value */
5228  SCIP_Real newub, /**< new upper bound */
5229  SCIP_Real oldub, /**< old upper bound */
5230  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5231  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5232  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5233  )
5234 {
5235  SCIP_CONSDATA* consdata;
5236  SCIP_VAR* var;
5237  SCIP_Real lb;
5238  SCIP_Bool infeasible;
5239  SCIP_Bool tightened;
5241  assert(cons != NULL);
5242  assert(!SCIPisInfinity(scip, newub));
5243 
5244  consdata = SCIPconsGetData(cons);
5245  assert(consdata != NULL);
5246  var = consdata->vars[pos];
5247  assert(var != NULL);
5248 
5249  lb = SCIPvarGetLbLocal(var);
5250  newub = SCIPadjustedVarUb(scip, var, newub);
5251 
5252  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5253  {
5254  SCIP_VARTYPE vartype;
5255 
5256  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5257  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5258 
5259  vartype = SCIPvarGetType(var);
5260 
5261  /* tighten upper bound */
5262  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5263 
5264  if( infeasible )
5265  {
5266  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5267  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5268 
5269  /* analyze conflict */
5270  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5271 
5272  *cutoff = TRUE;
5273  }
5274  else if( tightened )
5275  {
5276  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5277  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5278  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5279 
5280  (*nchgbds)++;
5281 
5282  /* if variable type was changed we might be able to upgrade the constraint */
5283  if( vartype != SCIPvarGetType(var) )
5284  consdata->upgradetried = FALSE;
5285  }
5286  }
5287  return SCIP_OKAY;
5288 }
5289 
5290 /** tighten lower bound */
5291 static
5293  SCIP* scip, /**< SCIP data structure */
5294  SCIP_CONS* cons, /**< linear constraint */
5295  int pos, /**< variable position */
5296  PROPRULE proprule, /**< propagation rule that deduced the value */
5297  SCIP_Real newlb, /**< new lower bound */
5298  SCIP_Real oldlb, /**< old lower bound */
5299  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5300  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5301  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5302  )
5303 {
5304  SCIP_CONSDATA* consdata;
5305  SCIP_VAR* var;
5306  SCIP_Real ub;
5307  SCIP_Bool infeasible;
5308  SCIP_Bool tightened;
5310  assert(cons != NULL);
5311  assert(!SCIPisInfinity(scip, newlb));
5312 
5313  consdata = SCIPconsGetData(cons);
5314  assert(consdata != NULL);
5315  var = consdata->vars[pos];
5316  assert(var != NULL);
5317 
5318  ub = SCIPvarGetUbLocal(var);
5319  newlb = SCIPadjustedVarLb(scip, var, newlb);
5320 
5321  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5322  {
5323  SCIP_VARTYPE vartype;
5324 
5325  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5326  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5327 
5328  vartype = SCIPvarGetType(var);
5329 
5330  /* tighten lower bound */
5331  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5332 
5333  if( infeasible )
5334  {
5335  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5336  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5337 
5338  /* analyze conflict */
5339  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5340 
5341  *cutoff = TRUE;
5342  }
5343  else if( tightened )
5344  {
5345  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5346  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5347  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5348 
5349  (*nchgbds)++;
5350 
5351  /* if variable type was changed we might be able to upgrade the constraint */
5352  if( vartype != SCIPvarGetType(var) )
5353  consdata->upgradetried = FALSE;
5354  }
5355  }
5356  return SCIP_OKAY;
5357 }
5358 
5359 /** tightens bounds of a single variable due to activity bounds (easy case) */
5360 static
5362  SCIP* scip, /**< SCIP data structure */
5363  SCIP_CONS* cons, /**< linear constraint */
5364  int pos, /**< position of the variable in the vars array */
5365  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5366  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5367  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5368  )
5369 {
5370  SCIP_CONSDATA* consdata;
5371  SCIP_VAR* var;
5372  SCIP_Real val;
5373  SCIP_Real lb;
5374  SCIP_Real ub;
5375  SCIP_Real lhs;
5376  SCIP_Real rhs;
5377 
5378  assert(scip != NULL);
5379  assert(cons != NULL);
5380  assert(cutoff != NULL);
5381  assert(nchgbds != NULL);
5382 
5383  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5384  if( SCIPconsIsModifiable(cons) )
5385  return SCIP_OKAY;
5386 
5387  consdata = SCIPconsGetData(cons);
5388  assert(consdata != NULL);
5389  assert(0 <= pos && pos < consdata->nvars);
5390 
5391  *cutoff = FALSE;
5392 
5393  var = consdata->vars[pos];
5394  assert(var != NULL);
5395 
5396  /* we cannot tighten bounds of multi-aggregated variables */
5398  return SCIP_OKAY;
5399 
5400  val = consdata->vals[pos];
5401  lhs = consdata->lhs;
5402  rhs = consdata->rhs;
5403  assert(!SCIPisZero(scip, val));
5404  assert(!SCIPisInfinity(scip, lhs));
5405  assert(!SCIPisInfinity(scip, -rhs));
5406 
5407  lb = SCIPvarGetLbLocal(var);
5408  ub = SCIPvarGetUbLocal(var);
5409  assert(SCIPisLE(scip, lb, ub));
5410 
5411  /* recompute activities if needed */
5412  if( !consdata->validactivities )
5413  consdataCalcActivities(scip, consdata);
5414  assert(consdata->validactivities);
5415  if( !consdata->validminact )
5416  consdataRecomputeMinactivity(scip, consdata);
5417  assert(consdata->validminact);
5418  if( !consdata->validmaxact )
5419  consdataRecomputeMaxactivity(scip, consdata);
5420  assert(consdata->validmaxact);
5421 
5422  if( val > 0.0 )
5423  {
5424  /* check, if we can tighten the variable's upper bound */
5425  if( !SCIPisInfinity(scip, rhs) )
5426  {
5427  SCIP_Real slack;
5428  SCIP_Real alpha;
5429 
5430  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5431  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5432  {
5433  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5434  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5435 
5436  *cutoff = TRUE;
5437  return SCIP_OKAY;
5438  }
5439 
5440  slack = rhs - consdata->minactivity;
5441 
5442  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5443  * it to zero
5444  */
5445  if( !SCIPisPositive(scip, slack) )
5446  slack = 0.0;
5447 
5448  alpha = val * (ub - lb);
5449  assert(!SCIPisNegative(scip, alpha));
5450 
5451  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5452  {
5453  SCIP_Real newub;
5454 
5455  /* compute new upper bound */
5456  newub = lb + (slack / val);
5457 
5458  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5459 
5460  if( *cutoff )
5461  {
5462  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5463  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5464 
5465  return SCIP_OKAY;
5466  }
5467 
5468  /* collect the new upper bound which is needed for the lower bound computation */
5469  ub = SCIPvarGetUbLocal(var);
5470  }
5471  }
5472 
5473  /* check, if we can tighten the variable's lower bound */
5474  if( !SCIPisInfinity(scip, -lhs) )
5475  {
5476  SCIP_Real slack;
5477  SCIP_Real alpha;
5478 
5479  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5480  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5481  {
5482  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5483  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5484 
5485  *cutoff = TRUE;
5486  return SCIP_OKAY;
5487  }
5488 
5489  slack = consdata->maxactivity - lhs;
5490 
5491  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5492  * it to zero
5493  */
5494  if( !SCIPisPositive(scip, slack) )
5495  slack = 0.0;
5496 
5497  alpha = val * (ub - lb);
5498  assert(!SCIPisNegative(scip, alpha));
5499 
5500  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5501  {
5502  SCIP_Real newlb;
5503 
5504  /* compute new lower bound */
5505  newlb = ub - (slack / val);
5506 
5507  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5508 
5509  if( *cutoff )
5510  {
5511  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5512  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5513 
5514  return SCIP_OKAY;
5515  }
5516  }
5517  }
5518  }
5519  else
5520  {
5521  /* check, if we can tighten the variable's lower bound */
5522  if( !SCIPisInfinity(scip, rhs) )
5523  {
5524  SCIP_Real slack;
5525  SCIP_Real alpha;
5526 
5527  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5528  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5529  {
5530  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5531  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5532 
5533  *cutoff = TRUE;
5534  return SCIP_OKAY;
5535  }
5536 
5537  slack = rhs - consdata->minactivity;
5538 
5539  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5540  * it to zero
5541  */
5542  if( !SCIPisPositive(scip, slack) )
5543  slack = 0.0;
5544 
5545  alpha = val * (lb - ub);
5546  assert(!SCIPisNegative(scip, alpha));
5547 
5548  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5549  {
5550  SCIP_Real newlb;
5551 
5552  /* compute new lower bound */
5553  newlb = ub + slack / val;
5554 
5555  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5556 
5557  if( *cutoff )
5558  {
5559  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5560  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5561 
5562  return SCIP_OKAY;
5563  }
5564  /* collect the new lower bound which is needed for the upper bound computation */
5565  lb = SCIPvarGetLbLocal(var);
5566  }
5567  }
5568 
5569  /* check, if we can tighten the variable's upper bound */
5570  if( !SCIPisInfinity(scip, -lhs) )
5571  {
5572  SCIP_Real slack;
5573  SCIP_Real alpha;
5574 
5575  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5576  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5577  {
5578  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5579  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5580 
5581  *cutoff = TRUE;
5582  return SCIP_OKAY;
5583  }
5584 
5585  slack = consdata->maxactivity - lhs;
5586 
5587  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5588  * it to zero
5589  */
5590  if( !SCIPisPositive(scip, slack) )
5591  slack = 0.0;
5592 
5593  alpha = val * (lb - ub);
5594  assert(!SCIPisNegative(scip, alpha));
5595 
5596  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5597  {
5598  SCIP_Real newub;
5599 
5600  /* compute new upper bound */
5601  newub = lb - (slack / val);
5602 
5603  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5604 
5605  if( *cutoff )
5606  {
5607  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5608  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5609 
5610  return SCIP_OKAY;
5611  }
5612  }
5613  }
5614  }
5615 
5616  return SCIP_OKAY;
5617 }
5618 
5619 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5620 static
5622  SCIP* scip, /**< SCIP data structure */
5623  SCIP_CONS* cons, /**< conflict detecting constraint */
5624  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5625  int nvars, /**< number of variables reasoning the infeasibility */
5626  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5627  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5628  )
5629 {
5630 #ifndef NDEBUG
5631  SCIP_CONSDATA* consdata;
5632 
5633  assert(scip != NULL);
5634  assert(cons != NULL);
5635 
5636  consdata = SCIPconsGetData(cons);
5637  assert(consdata != NULL);
5638  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5639 #endif
5640 
5641  /* conflict analysis can only be applied in solving stage and if it is turned on */
5643  return SCIP_OKAY;
5644 
5645  /* initialize conflict analysis */
5647 
5648  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5649  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5650 
5651  /* add reasoning variables to conflict candidate queue which led to the conflict */
5652  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5653 
5654  /* analyze the conflict */
5655  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5656 
5657  return SCIP_OKAY;
5658 }
5659 
5660 /** propagate ranged rows
5661  *
5662  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5663  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5664  * variables better.
5665  *
5666  * Example:
5667  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5668  *
5669  * x3 needs to be a multiple of 3, so the instance is infeasible.
5670  *
5671  * Example:
5672  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5673  *
5674  * The only posible value for x3 is 2, so the variable will be fixed.
5675  *
5676  * @todo add holes if possible
5677  */
5678 static
5680  SCIP* scip, /**< SCIP data structure */
5681  SCIP_CONS* cons, /**< linear constraint */
5682  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5683  int* nfixedvars, /**< pointer to count number of fixed variables */
5684  int* nchgbds, /**< pointer to count the number of bound changes */
5685  int* naddconss /**< pointer to count number of added constraints */
5686  )
5687 {
5688  SCIP_CONSHDLRDATA* conshdlrdata;
5689  SCIP_CONSHDLR* conshdlr;
5690  SCIP_CONSDATA* consdata;
5691  SCIP_VAR** infcheckvars;
5692  SCIP_Real* infcheckvals;
5693  SCIP_Real minactinfvars;
5694  SCIP_Real maxactinfvars;
5695  SCIP_Real lb;
5697  SCIP_Real feastol;
5698  SCIP_Real fixedact;
5699  SCIP_Real lhs;
5700  SCIP_Real rhs;
5701  SCIP_Real absminbincoef;
5702  SCIP_Longint gcd;
5703  SCIP_Longint gcdtmp;
5704  SCIP_Bool minactinfvarsinvalid;
5705  SCIP_Bool maxactinfvarsinvalid;
5706  SCIP_Bool possiblegcd;
5707  SCIP_Bool gcdisone;
5708  SCIP_Bool addartconss;
5709  int ninfcheckvars;
5710  int nunfixedvars;
5711  int nfixedconsvars;
5712  int ncontvars;
5713  int pos;
5714  int v;
5715 
5716  assert(scip != NULL);
5717  assert(cons != NULL);
5718  assert(cutoff != NULL);
5719  assert(nfixedvars != NULL);
5720  assert(nchgbds != NULL);
5721  assert(naddconss != NULL);
5722 
5723  /* modifiable constraint can be changed so we do not have all necessary information */
5724  if( SCIPconsIsModifiable(cons) )
5725  return SCIP_OKAY;
5726 
5727  consdata = SCIPconsGetData(cons);
5728  assert(consdata != NULL);
5729 
5730  /* we already did full ranged row propagation */
5731  if( consdata->rangedrowpropagated == 2 )
5732  return SCIP_OKAY;
5733 
5734  /* at least three variables are needed */
5735  if( consdata->nvars < 3 )
5736  return SCIP_OKAY;
5737 
5738  /* do nothing on normal inequalities */
5739  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5740  return SCIP_OKAY;
5741 
5742  /* get constraint handler data */
5743  conshdlr = SCIPconsGetHdlr(cons);
5744  assert(conshdlr != NULL);
5745  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5746  assert(conshdlrdata != NULL);
5747 
5748  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5749 
5750  /* we may add artificial constraints */
5751  if( addartconss )
5752  consdata->rangedrowpropagated = 2;
5753  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5754  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5755  * artificial constraints
5756  */
5757  else
5758  {
5759  if( consdata->rangedrowpropagated > 0 )
5760  return SCIP_OKAY;
5761 
5762  consdata->rangedrowpropagated = 1;
5763  }
5764  fixedact = 0;
5765  nfixedconsvars = 0;
5766  /* calculate fixed activity and number of fixed variables */
5767  for( v = consdata->nvars - 1; v >= 0; --v )
5768  {
5769  /* all zero coefficients should be eliminated */
5770  assert(!SCIPisZero(scip, consdata->vals[v]));
5771 
5772  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5773  {
5774  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5775  ++nfixedconsvars;
5776  }
5777  }
5778 
5779  /* do not work with huge fixed activities */
5780  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5781  return SCIP_OKAY;
5782 
5783  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5784  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5785  lhs = consdata->lhs - fixedact;
5786  rhs = consdata->rhs - fixedact;
5787  nunfixedvars = consdata->nvars - nfixedconsvars;
5788 
5789  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5790  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5791  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5792 
5793  absminbincoef = SCIP_REAL_MAX;
5794  ncontvars = 0;
5795  gcdisone = TRUE;
5796  possiblegcd = TRUE;
5797 
5798  /* we now partition all unfixed variables in two groups:
5799  *
5800  * the first one contains all integral variable with integral
5801  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5802  * given
5803  *
5804  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5805  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5806  */
5807 
5808  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5809  * variables
5810  */
5811  ninfcheckvars = 0;
5812  v = -1;
5813  pos = -1;
5814  do
5815  {
5816  ++v;
5817 
5818  /* partition the variables, do not change the order of collection, because it might be used later on */
5819  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5820  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5821  {
5822  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5823  {
5824  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5825  {
5826  ++ncontvars;
5827  }
5828  else if( SCIPvarIsBinary(consdata->vars[v]) )
5829  {
5830  SCIP_Real absval;
5831 
5832  absval = REALABS(consdata->vals[v]);
5833 
5834  if( absminbincoef > absval )
5835  absminbincoef = absval;
5836  }
5837 
5838  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5839  possiblegcd = FALSE;
5840  infcheckvars[ninfcheckvars] = consdata->vars[v];
5841  infcheckvals[ninfcheckvars] = consdata->vals[v];
5842  ++ninfcheckvars;
5843 
5844  if( pos == -1 )
5845  pos = v;
5846  }
5847  ++v;
5848  }
5849  }
5850  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5851 
5852  /* if the first group of variables is empty, we stop */
5853  /* @todo try to propagate/split up a constraint of the form:
5854  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5855  * 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]
5856  */
5857  if( v == consdata->nvars )
5858  goto TERMINATE;
5859 
5860  /* we need at least two non-continuous variables */
5861  if( ncontvars + 2 > nunfixedvars )
5862  goto TERMINATE;
5863 
5864  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5865  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5866 
5867  feastol = SCIPfeastol(scip);
5868 
5869  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5870  assert(gcd >= 2);
5871 
5872  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5873  * calculate gcd over the first part of variables */
5874  for( ; v < consdata->nvars; ++v )
5875  {
5876  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5877  continue;
5878 
5879  if( SCIPvarIsBinary(consdata->vars[v]) )
5880  {
5881  SCIP_Real absval;
5882 
5883  absval = REALABS(consdata->vals[v]);
5884 
5885  if( absminbincoef > absval )
5886  absminbincoef = absval;
5887  }
5888 
5889  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5890  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5891  {
5892  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5893  ++ncontvars;
5894 
5895  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5896  possiblegcd = FALSE;
5897  infcheckvars[ninfcheckvars] = consdata->vars[v];
5898  infcheckvals[ninfcheckvars] = consdata->vals[v];
5899 
5900  ++ninfcheckvars;
5901 
5902  if( pos == -1 )
5903  pos = v;
5904  }
5905  else
5906  {
5907  assert(REALABS(consdata->vals[v]) > 1.5);
5908 
5909  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5910  assert(gcdtmp >= 1);
5911 
5912  if( gcdtmp == 1 )
5913  {
5914  infcheckvars[ninfcheckvars] = consdata->vars[v];
5915  infcheckvals[ninfcheckvars] = consdata->vals[v];
5916 
5917  ++ninfcheckvars;
5918 
5919  if( pos == -1 )
5920  pos = v;
5921  }
5922  else
5923  gcd = gcdtmp;
5924  }
5925  }
5926  assert(gcd >= 2);
5927 
5928  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5929  * normalizeCons() */
5930  if( ninfcheckvars == 0 )
5931  goto TERMINATE;
5932 
5933  assert(pos >= 0);
5934 
5935  minactinfvarsinvalid = FALSE;
5936  maxactinfvarsinvalid = FALSE;
5937  maxactinfvars = 0.0;
5938  minactinfvars = 0.0;
5939 
5940  /* calculate activities over all infcheckvars */
5941  for( v = ninfcheckvars - 1; v >= 0; --v )
5942  {
5943  lb = SCIPvarGetLbLocal(infcheckvars[v]);
5944  ub = SCIPvarGetUbLocal(infcheckvars[v]);
5945 
5946  if( SCIPisInfinity(scip, -lb) )
5947  {
5948  if( infcheckvals[v] < 0.0 )
5949  maxactinfvarsinvalid = TRUE;
5950  else
5951  minactinfvarsinvalid = TRUE;
5952  }
5953  else
5954  {
5955  if( infcheckvals[v] < 0.0 )
5956  maxactinfvars += infcheckvals[v] * lb;
5957  else
5958  minactinfvars += infcheckvals[v] * lb;
5959  }
5960 
5961  if( SCIPisInfinity(scip, ub) )
5962  {
5963  if( infcheckvals[v] > 0.0 )
5964  maxactinfvarsinvalid = TRUE;
5965  else
5966  minactinfvarsinvalid = TRUE;
5967  }
5968  else
5969  {
5970  if( infcheckvals[v] > 0.0 )
5971  maxactinfvars += infcheckvals[v] * ub;
5972  else
5973  minactinfvars += infcheckvals[v] * ub;
5974  }
5975 
5976  /* better abort on to big values */
5977  if( SCIPisHugeValue(scip, -minactinfvars) )
5978  minactinfvarsinvalid = TRUE;
5979  if( SCIPisHugeValue(scip, maxactinfvars) )
5980  maxactinfvarsinvalid = TRUE;
5981 
5982  if( minactinfvarsinvalid || maxactinfvarsinvalid )
5983  goto TERMINATE;
5984  }
5985  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
5986 
5987  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
5988  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
5989 
5990  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
5991  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
5992  * activities */
5993  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
5994  * !!!note!!!
5995  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
5996  * are not at their global bound
5997  */
5998 
5999  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6000  * infeasibility */
6001  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6002  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6003  {
6004  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6005  SCIPdebugPrintCons(scip, cons, NULL);
6006 
6007  /* start conflict analysis */
6008  /* @todo improve conflict analysis by adding relaxed bounds */
6009  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6010 
6011  *cutoff = TRUE;
6012  }
6013  else if( ncontvars == 0 )
6014  {
6015  SCIP_Longint gcdinfvars = -1;
6016 
6017  /* check for gcd over all infcheckvars */
6018  if( possiblegcd )
6019  {
6020  v = ninfcheckvars - 1;
6021  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6022  assert(gcdinfvars >= 2);
6023 
6024  for( ; v >= 0 && gcdinfvars >= 2; --v )
6025  {
6026  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6027  }
6028  }
6029  else if( gcdisone )
6030  gcdinfvars = 1;
6031 
6032  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6033 
6034  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6035  if( gcdinfvars >= 1 )
6036  {
6037  SCIP_Real value;
6038  SCIP_Real value2;
6039  SCIP_Real minvalue = SCIP_INVALID;
6040  SCIP_Real maxvalue = SCIP_INVALID;
6041  int nsols = 0;
6042 
6043  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6044 
6045  /* check how many possible solutions exist */
6046  while( SCIPisLE(scip, value, maxactinfvars) )
6047  {
6048  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6049 
6050  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6051  {
6052  ++nsols;
6053 
6054  /* early termination if we found more than two solutions */
6055  if( nsols == 3 )
6056  break;
6057 
6058  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6059  minvalue = value;
6060 
6061  maxvalue = value;
6062  }
6063  value += gcdinfvars;
6064  }
6065  assert(nsols < 2 || minvalue <= maxvalue);
6066 
6067  /* determine last possible solution for better bounding */
6068  if( nsols == 3 )
6069  {
6070 #ifndef NDEBUG
6071  SCIP_Real secondsolval = maxvalue;
6072 #endif
6073  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6074 
6075  /* check how many possible solutions exist */
6076  while( SCIPisGE(scip, value, minactinfvars) )
6077  {
6078  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6079 
6080  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6081  {
6082  maxvalue = value;
6083  assert(maxvalue > minvalue);
6084  break;
6085  }
6086  value -= gcdinfvars;
6087  }
6088  assert(maxvalue > secondsolval);
6089  }
6090 
6091  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6092  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6093 
6094  /* no possible solution found */
6095  if( nsols == 0 )
6096  {
6097  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6098  gcdinfvars, gcd, lhs, rhs);
6099  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6100  SCIPdebugPrintCons(scip, cons, NULL);
6101 
6102  /* start conflict analysis */
6103  /* @todo improve conflict analysis by adding relaxed bounds */
6104  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6105 
6106  *cutoff = TRUE;
6107  }
6108  /* if only one solution exist we can extract a new constraint or fix variables */
6109  else if( nsols == 1 )
6110  {
6111  assert(minvalue == maxvalue); /*lint !e777*/
6112 
6113  /* we can fix the only variable in our second set of variables */
6114  if( ninfcheckvars == 1 )
6115  {
6116  SCIP_Bool fixed;
6117 
6118  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6119 
6120  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6121  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6122  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6123 
6124  /* fix variable to only possible value */
6125  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6126  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6127 
6128  if( *cutoff )
6129  {
6130  /* start conflict analysis */
6131  /* @todo improve conflict analysis by adding relaxed bounds */
6132  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6133  }
6134 
6135  if( fixed )
6136  ++(*nfixedvars);
6137  }
6138  else
6139  {
6140  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6141  if( ninfcheckvars == nunfixedvars - 1 )
6142  {
6143  SCIP_Real bound;
6144  SCIP_Bool foundvar = FALSE;
6145  SCIP_Bool fixed;
6146  int w = 0;
6147 
6148  assert(ninfcheckvars > 0);
6149 
6150  /* find variable which is not an infcheckvar and fix it */
6151  for( v = 0; v < consdata->nvars - 1; ++v )
6152  {
6153  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6154  {
6155  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6156  {
6157 #ifndef NDEBUG
6158  int v2 = v + 1;
6159  int w2 = w;
6160 
6161  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6162 
6163  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6164  {
6165  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6166  continue;
6167 
6168  assert(consdata->vars[v2] == infcheckvars[w2]);
6169  ++w2;
6170  }
6171  assert(w2 == ninfcheckvars);
6172 #endif
6173  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6174 
6175  foundvar = TRUE;
6176 
6177  if( consdata->vals[v] < 0 )
6178  {
6179  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6180  }
6181  else
6182  {
6183  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6184  }
6185 
6186  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6187  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6188  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6189 
6190  /* fix variable to only possible value */
6191  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6192  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6193 
6194  if( *cutoff )
6195  {
6196  /* start conflict analysis */
6197  /* @todo improve conflict analysis by adding relaxed bounds */
6198  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6199  consdata->vars[v], bound) );
6200  }
6201 
6202  if( fixed )
6203  ++(*nfixedvars);
6204 
6205  break;
6206  }
6207 
6208  ++w;
6209  }
6210  }
6211 
6212  /* maybe last variable was the not infcheckvar */
6213  if( !foundvar )
6214  {
6215  assert(v == consdata->nvars - 1);
6216  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6217 
6218  if( consdata->vals[v] < 0 )
6219  {
6220  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6221  }
6222  else
6223  {
6224  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6225  }
6226 
6227  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6228  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6229  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6230 
6231  /* fix variable to only possible value */
6232  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6233  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6234 
6235  if( *cutoff )
6236  {
6237  /* start conflict analysis */
6238  /* @todo improve conflict analysis by adding relaxed bounds */
6239  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6240  consdata->vars[v], bound) );
6241  }
6242 
6243  if( fixed )
6244  ++(*nfixedvars);
6245  }
6246  }
6247  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6248  {
6249  /* aggregation possible if we have two variables, but this will be done later on */
6250  SCIP_CONS* newcons;
6251  char name[SCIP_MAXSTRLEN];
6252 
6253  /* create, add, and release new artificial constraint */
6254  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6255  ++conshdlrdata->naddconss;
6256 
6257  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6258 
6259  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6260  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6261  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6262 
6263  SCIPdebugPrintCons(scip, newcons, NULL);
6264 
6265  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6266 
6267  ++(*naddconss);
6268  }
6269  }
6270  }
6271  /* at least two solutions */
6272  else
6273  {
6274  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6275 
6276  /* only one variable in the second set, so we can bound this variables */
6277  if( ninfcheckvars == 1 )
6278  {
6279  SCIP_Bool tightened;
6280  SCIP_Real newlb;
6281  SCIP_Real newub;
6282 
6283  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6284 
6285  if( infcheckvals[0] < 0 )
6286  {
6287  newlb = maxvalue/infcheckvals[0];
6288  newub = minvalue/infcheckvals[0];
6289  }
6290  else
6291  {
6292  newlb = minvalue/infcheckvals[0];
6293  newub = maxvalue/infcheckvals[0];
6294  }
6295  assert(newlb < newub);
6296 
6297  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6298  {
6299  /* update lower bound of variable */
6300  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6301  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6302 
6303  /* tighten variable lower bound to minimal possible value */
6304  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6305  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6306 
6307  if( *cutoff )
6308  {
6309  /* start conflict analysis */
6310  /* @todo improve conflict analysis by adding relaxed bounds */
6311  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6312  }
6313 
6314  if( tightened )
6315  ++(*nchgbds);
6316  }
6317 
6318  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6319  {
6320  /* update upper bound of variable */
6321  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6322  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6323 
6324  /* tighten variable upper bound to maximal possible value */
6325  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6326  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6327 
6328  if( *cutoff )
6329  {
6330  /* start conflict analysis */
6331  /* @todo improve conflict analysis by adding relaxed bounds */
6332  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6333  }
6334 
6335  if( tightened )
6336  ++(*nchgbds);
6337  }
6338  }
6339  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6340  else if( ninfcheckvars == nunfixedvars - 1 )
6341  {
6342  SCIP_Bool foundvar = FALSE;
6343  SCIP_Bool tightened;
6344  SCIP_Real newlb;
6345  SCIP_Real newub;
6346  int w = 0;
6347 
6348  assert(ninfcheckvars > 0);
6349  assert(minvalue < maxvalue);
6350 
6351  /* find variable which is not an infcheckvar and fix it */
6352  for( v = 0; v < consdata->nvars - 1; ++v )
6353  {
6354  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6355  {
6356  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6357  {
6358 #ifndef NDEBUG
6359  int v2 = v + 1;
6360  int w2 = w;
6361 
6362  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6363 
6364  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6365  {
6366  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6367  continue;
6368 
6369  assert(consdata->vars[v2] == infcheckvars[w2]);
6370  ++w2;
6371  }
6372  assert(w2 == ninfcheckvars);
6373 #endif
6374 
6375  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6376  foundvar = TRUE;
6377 
6378  if( consdata->vals[v] < 0 )
6379  {
6380  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6381  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6382  }
6383  else
6384  {
6385  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6386  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6387  }
6388  assert(SCIPisLE(scip, newlb, newub));
6389 
6390  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6391  {
6392  /* update lower bound of variable */
6393  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6394  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6395 
6396  /* tighten variable lower bound to minimal possible value */
6397  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6398  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6399 
6400  if( *cutoff )
6401  {
6402  /* start conflict analysis */
6403  /* @todo improve conflict analysis by adding relaxed bounds */
6404  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6405  consdata->vars[v], newlb) );
6406  }
6407 
6408  if( tightened )
6409  ++(*nchgbds);
6410  }
6411 
6412  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6413  {
6414  /* update upper bound of variable */
6415  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6416  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6417 
6418  /* tighten variable upper bound to maximal possible value */
6419  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6420  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6421 
6422  if( *cutoff )
6423  {
6424  /* start conflict analysis */
6425  /* @todo improve conflict analysis by adding relaxed bounds */
6426  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6427  consdata->vars[v], newub) );
6428  }
6429 
6430  if( tightened )
6431  ++(*nchgbds);
6432  }
6433 
6434  break;
6435  }
6436 
6437  ++w;
6438  }
6439  }
6440 
6441  /* maybe last variable was the not infcheckvar */
6442  if( !foundvar )
6443  {
6444  assert(v == consdata->nvars - 1);
6445  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6446 
6447  if( consdata->vals[v] < 0 )
6448  {
6449  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6450  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6451  }
6452  else
6453  {
6454  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6455  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6456  }
6457  assert(SCIPisLE(scip, newlb, newub));
6458 
6459  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6460  {
6461  /* update lower bound of variable */
6462  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6463  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6464 
6465  /* tighten variable lower bound to minimal possible value */
6466  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6467  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6468 
6469  if( *cutoff )
6470  {
6471  /* start conflict analysis */
6472  /* @todo improve conflict analysis by adding relaxed bounds */
6473  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6474  }
6475 
6476  if( tightened )
6477  ++(*nchgbds);
6478  }
6479 
6480  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6481  {
6482  /* update upper bound of variable */
6483  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6484  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6485 
6486  /* tighten variable upper bound to maximal possible value */
6487  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6488  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6489 
6490  if( *cutoff )
6491  {
6492  /* start conflict analysis */
6493  /* @todo improve conflict analysis by adding relaxed bounds */
6494  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6495  }
6496 
6497  if( tightened )
6498  ++(*nchgbds);
6499  }
6500  }
6501  }
6502  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6503  * region for our infcheckvars, if possible
6504  */
6505  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6506  {
6507  SCIP_CONS* newcons;
6508  char name[SCIP_MAXSTRLEN];
6509  SCIP_Real newlhs;
6510  SCIP_Real newrhs;
6511 
6512  assert(maxvalue > minvalue);
6513 
6514  if( SCIPisGT(scip, minvalue, minactinfvars) )
6515  newlhs = minvalue;
6516  else
6517  newlhs = -SCIPinfinity(scip);
6518 
6519  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6520  newrhs = maxvalue;
6521  else
6522  newrhs = SCIPinfinity(scip);
6523 
6524  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6525  {
6526  /* create, add, and release new artificial constraint */
6527  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6528  ++conshdlrdata->naddconss;
6529 
6530  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6531 
6532  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6533  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6534  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6535 
6536  SCIPdebugPrintCons(scip, newcons, NULL);
6537  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6538 
6539  ++(*naddconss);
6540  }
6541  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6542  * should be maxvalue */
6543  }
6544  }
6545  }
6546  }
6547  else if( addartconss && ncontvars < ninfcheckvars )
6548  {
6549  SCIP_Real maxact = 0.0;
6550  SCIP_Real minact = 0.0;
6551  int w = 0;
6552 
6553  /* compute activities of non-infcheckvars */
6554  for( v = 0; v < consdata->nvars; ++v )
6555  {
6556  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6557  {
6558  ++w;
6559  continue;
6560  }
6561 
6562  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6563  {
6564  if( SCIPvarIsBinary(consdata->vars[v]) )
6565  {
6566  if( consdata->vals[v] > 0.0 )
6567  maxact += consdata->vals[v];
6568  else
6569  minact += consdata->vals[v];
6570  }
6571  else
6572  {
6573  SCIP_Real tmpval;
6574 
6575  assert(SCIPvarIsIntegral(consdata->vars[v]));
6576 
6577  if( consdata->vals[v] > 0.0 )
6578  {
6579  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6580 
6581  if( SCIPisHugeValue(scip, -tmpval) )
6582  break;
6583 
6584  minact += tmpval;
6585 
6586  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6587 
6588  if( SCIPisHugeValue(scip, tmpval) )
6589  break;
6590 
6591  maxact += tmpval;
6592  }
6593  else
6594  {
6595  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6596 
6597  if( SCIPisHugeValue(scip, -tmpval) )
6598  break;
6599 
6600  minact += tmpval;
6601 
6602  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6603 
6604  if( SCIPisHugeValue(scip, tmpval) )
6605  break;
6606 
6607  maxact += tmpval;
6608  }
6609  }
6610  }
6611  }
6612  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6613  {
6614  SCIP_CONS* newcons;
6615  char name[SCIP_MAXSTRLEN];
6616  SCIP_Real newlhs;
6617  SCIP_Real newrhs;
6618 
6619  assert(maxact > minact);
6620  assert(w == ninfcheckvars);
6621 
6622  newlhs = lhs - maxact;
6623  newrhs = rhs - minact;
6624  assert(newlhs < newrhs);
6625 
6626  /* create, add, and release new artificial constraint */
6627  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6628  ++conshdlrdata->naddconss;
6629 
6630  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6631 
6632  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6633  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6634  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6635 
6636  SCIPdebugPrintCons(scip, newcons, NULL);
6637  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6638 
6639  ++(*naddconss);
6640  }
6641  }
6642 
6643  TERMINATE:
6644  SCIPfreeBufferArray(scip, &infcheckvals);
6645  SCIPfreeBufferArray(scip, &infcheckvars);
6646 
6647  return SCIP_OKAY;
6648 }
6649 
6650 /** tightens bounds of a single variable due to activity bounds */
6651 static
6653  SCIP* scip, /**< SCIP data structure */
6654  SCIP_CONS* cons, /**< linear constraint */
6655  int pos, /**< position of the variable in the vars array */
6656  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6657  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6658  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6659  )
6660 {
6661  SCIP_CONSDATA* consdata;
6662  SCIP_VAR* var;
6663  SCIP_Real val;
6664  SCIP_Real lb;
6665  SCIP_Real ub;
6666  SCIP_Real minresactivity;
6667  SCIP_Real maxresactivity;
6668  SCIP_Real lhs;
6670  SCIP_Bool infeasible;
6671  SCIP_Bool tightened;
6672  SCIP_Bool minisrelax;
6673  SCIP_Bool maxisrelax;
6674  SCIP_Bool isminsettoinfinity;
6675  SCIP_Bool ismaxsettoinfinity;
6676 
6677  assert(scip != NULL);
6678  assert(cons != NULL);
6679  assert(cutoff != NULL);
6680  assert(nchgbds != NULL);
6681 
6682  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6683  if( SCIPconsIsModifiable(cons) )
6684  return SCIP_OKAY;
6685 
6686  consdata = SCIPconsGetData(cons);
6687  assert(consdata != NULL);
6688  assert(0 <= pos && pos < consdata->nvars);
6689 
6690  *cutoff = FALSE;
6691 
6692  var = consdata->vars[pos];
6693 
6694  /* we cannot tighten bounds of multi-aggregated variables */
6696  return SCIP_OKAY;
6697 
6698  val = consdata->vals[pos];
6699  lhs = consdata->lhs;
6700  rhs = consdata->rhs;
6701  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6702  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6703  assert(var != NULL);
6704  assert(!SCIPisZero(scip, val));
6705  assert(!SCIPisInfinity(scip, lhs));
6706  assert(!SCIPisInfinity(scip, -rhs));
6707 
6708  lb = SCIPvarGetLbLocal(var);
6709  ub = SCIPvarGetUbLocal(var);
6710  assert(SCIPisLE(scip, lb, ub));
6711 
6712  if( val > 0.0 )
6713  {
6714  /* check, if we can tighten the variable's bounds */
6715  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6716  {
6717  SCIP_Real newub;
6718 
6719  newub = (rhs - minresactivity)/val;
6720 
6721  if( !SCIPisInfinity(scip, newub) &&
6722  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6723  {
6724  SCIP_Bool activityunreliable;
6725  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6726 
6727  /* check minresactivities for reliability */
6728  if( activityunreliable )
6729  {
6730  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6731  newub = (rhs - minresactivity)/val;
6732  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6733  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6734  && (!force || !SCIPisLT(scip, newub, ub)));
6735  }
6736 
6737  if( !activityunreliable )
6738  {
6739  /* tighten upper bound */
6740  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6741  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6742  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6743  &infeasible, &tightened) );
6744  if( infeasible )
6745  {
6746  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6747  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6748 
6749  /* analyze conflict */
6750  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6751 
6752  *cutoff = TRUE;
6753  return SCIP_OKAY;
6754  }
6755  if( tightened )
6756  {
6757  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6758  assert(SCIPisFeasLE(scip, ub, newub));
6759  (*nchgbds)++;
6760 
6761  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6762  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6763  }
6764  }
6765  }
6766  }
6767 
6768  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6769  {
6770  SCIP_Real newlb;
6771 
6772  newlb = (lhs - maxresactivity)/val;
6773  if( !SCIPisInfinity(scip, -newlb) &&
6774  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6775  {
6776  /* check maxresactivities for reliability */
6777  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6778  {
6779  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6780  newlb = (lhs - maxresactivity)/val;
6781 
6782  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6783  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6784  && (!force || !SCIPisGT(scip, newlb, lb))) )
6785  return SCIP_OKAY;
6786  }
6787 
6788  /* tighten lower bound */
6789  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6790  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6791  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6792  &infeasible, &tightened) );
6793  if( infeasible )
6794  {
6795  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6796  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6797 
6798  /* analyze conflict */
6799  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6800 
6801  *cutoff = TRUE;
6802  return SCIP_OKAY;
6803  }
6804  if( tightened )
6805  {
6806  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6807  assert(SCIPisFeasGE(scip, lb, newlb));
6808  (*nchgbds)++;
6809  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6810  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6811  }
6812  }
6813  }
6814  }
6815  else
6816  {
6817  /* check, if we can tighten the variable's bounds */
6818  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6819  {
6820  SCIP_Real newlb;
6821 
6822  newlb = (rhs - minresactivity)/val;
6823  if( !SCIPisInfinity(scip, -newlb) &&
6824  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6825  {
6826  SCIP_Bool activityunreliable;
6827  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6828  /* check minresactivities for reliability */
6829  if( activityunreliable )
6830  {
6831  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6832  newlb = (rhs - minresactivity)/val;
6833 
6834  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6835  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6836  && (!force || !SCIPisGT(scip, newlb, lb)));
6837  }
6838 
6839  if( !activityunreliable )
6840  {
6841  /* tighten lower bound */
6842  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6843  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6844  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6845  &infeasible, &tightened) );
6846  if( infeasible )
6847  {
6848  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6849  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6850 
6851  /* analyze conflict */
6852  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6853 
6854  *cutoff = TRUE;
6855  return SCIP_OKAY;
6856  }
6857  if( tightened )
6858  {
6859  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6860  assert(SCIPisFeasGE(scip, lb, newlb));
6861  (*nchgbds)++;
6862  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6863  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6864  }
6865  }
6866  }
6867  }
6868 
6869  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6870  {
6871  SCIP_Real newub;
6872 
6873  newub = (lhs - maxresactivity)/val;
6874  if( !SCIPisInfinity(scip, newub) &&
6875  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6876  {
6877  /* check maxresactivities for reliability */
6878  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6879  {
6880  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6881  newub = (lhs - maxresactivity)/val;
6882 
6883  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6884  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6885  && (!force || !SCIPisLT(scip, newub, ub))) )
6886  return SCIP_OKAY;
6887  }
6888 
6889  /* tighten upper bound */
6890  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6891  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6892  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6893  &infeasible, &tightened) );
6894  if( infeasible )
6895  {
6896  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6897  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6898 
6899  /* analyze conflict */
6900  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6901 
6902  *cutoff = TRUE;
6903  return SCIP_OKAY;
6904  }
6905  if( tightened )
6906  {
6907  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6908  assert(SCIPisFeasLE(scip, ub, newub));
6909  (*nchgbds)++;
6910  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6911  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6912  }
6913  }
6914  }
6915  }
6916 
6917  return SCIP_OKAY;
6918 }
6919 
6920 #define MAXTIGHTENROUNDS 10
6921 
6922 /** tightens bounds of variables in constraint due to activity bounds */
6923 static
6925  SCIP* scip, /**< SCIP data structure */
6926  SCIP_CONS* cons, /**< linear constraint */
6927  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6928  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6929  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6930  int* nchgbds /**< pointer to count the total number of tightened bounds */
6931  )
6932 {
6933  SCIP_CONSDATA* consdata;
6934  unsigned int tightenmode;
6935  int nvars;
6936  int nrounds;
6937  int lastchange;
6938  int oldnchgbds;
6939 #ifndef SCIP_DEBUG
6940  int oldnchgbdstotal;
6941 #endif
6942  int v;
6943  SCIP_Bool force;
6944  SCIP_Bool easycase;
6945 
6946  assert(scip != NULL);
6947  assert(cons != NULL);
6948  assert(nchgbds != NULL);
6949  assert(cutoff != NULL);
6950 
6951  *cutoff = FALSE;
6952 
6953  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6954  if( SCIPconsIsModifiable(cons) )
6955  return SCIP_OKAY;
6956 
6957  /* if a constraint was created after presolve, then it may hold fixed variables
6958  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
6959  * thus, ensure here again that variable fixings have been applied
6960  */
6961  SCIP_CALL( applyFixings(scip, cons, cutoff) );
6962  if( *cutoff )
6963  return SCIP_OKAY;
6964 
6965  /* check if constraint has any chances of tightening bounds */
6966  if( !canTightenBounds(scip, cons) )
6967  return SCIP_OKAY;
6968 
6969  consdata = SCIPconsGetData(cons);
6970  assert(consdata != NULL);
6971 
6972  nvars = consdata->nvars;
6973  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
6974 
6975  /* we are at the root node or during presolving */
6976  if( SCIPgetDepth(scip) < 1 )
6977  tightenmode = 2;
6978  else
6979  tightenmode = 1;
6980 
6981  /* stop if we already tightened the constraint and the tightening is not forced */
6982  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
6983  return SCIP_OKAY;
6984 
6985  /* ensure that the variables are properly sorted */
6986  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
6987  {
6988  SCIP_CALL( consdataSort(scip, consdata) );
6989  assert(consdata->binvarssorted);
6990  }
6991 
6992  /* update maximal activity delta if necessary */
6993  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
6994  consdataRecomputeMaxActivityDelta(scip, consdata);
6995 
6996  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
6997  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
6998  checkMaxActivityDelta(scip, consdata);
6999 
7000  /* this may happen if all variables are fixed */
7001  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7002  return SCIP_OKAY;
7003 
7004  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7005  {
7006  SCIP_Real slack;
7007  SCIP_Real surplus;
7008  SCIP_Real minactivity;
7009  SCIP_Real maxactivity;
7010  SCIP_Bool minisrelax;
7011  SCIP_Bool maxisrelax;
7012 
7013  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7014  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
7015  assert(!SCIPisInfinity(scip, minactivity));
7016  assert(!SCIPisInfinity(scip, -maxactivity));
7017 
7018  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7019  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7020 
7021  /* check if the constraint will propagate */
7022  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7023  return SCIP_OKAY;
7024  }
7025 
7026  /* check if we can use fast implementation for easy and numerically well behaved cases */
7027  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7028 
7029  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7030  lastchange = -1;
7031  oldnchgbds = 0;
7032 
7033 #ifndef SCIP_DEBUG
7034  oldnchgbdstotal = *nchgbds;
7035 #endif
7036 
7037  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7038  {
7039  /* mark the constraint to have the variables' bounds tightened */
7040  consdata->boundstightened = (unsigned int)tightenmode;
7041 
7042  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7043  * sorting enables skipping variables
7044  */
7045  v = 0;
7046  while( v < nvars && v != lastchange && !(*cutoff) )
7047  {
7048  oldnchgbds = *nchgbds;
7049 
7050  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
7051 
7052  if( easycase )
7053  {
7054  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7055  }
7056  else
7057  {
7058  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7059  }
7060 
7061  /* if there was no progress, skip the rest of the binary variables */
7062  if( *nchgbds > oldnchgbds )
7063  {
7064  lastchange = v;
7065  ++v;
7066  }
7067  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
7068  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7069  v = consdata->nbinvars;
7070  else
7071  ++v;
7072  }
7073 
7074 #ifndef SCIP_DEBUG
7075  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7076  *nchgbds - oldnchgbdstotal, nrounds);
7077  oldnchgbdstotal += oldnchgbds;
7078 #endif
7079  }
7080 
7081 #ifndef NDEBUG
7082  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7083  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7084 #endif
7085 
7086  return SCIP_OKAY;
7087 }
7088 
7089 /** checks linear constraint for feasibility of given solution or current solution */
7090 static
7092  SCIP* scip, /**< SCIP data structure */
7093  SCIP_CONS* cons, /**< linear constraint */
7094  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7095  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7096  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7097  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7098  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7099  )
7100 {
7101  SCIP_CONSDATA* consdata;
7102  SCIP_Real activity;
7103  SCIP_Real absviol;
7104  SCIP_Real relviol;
7105  SCIP_Real lhsviol;
7106  SCIP_Real rhsviol;
7107 
7108  assert(scip != NULL);
7109  assert(cons != NULL);
7110  assert(violated != NULL);
7111 
7112  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7113  SCIPdebugPrintCons(scip, cons, NULL);
7114 
7115  consdata = SCIPconsGetData(cons);
7116  assert(consdata != NULL);
7117 
7118  *violated = FALSE;
7119 
7120  if( consdata->row != NULL )
7121  {
7122  if( !checklprows && SCIProwIsInLP(consdata->row) )
7123  return SCIP_OKAY;
7124  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7125  activity = consdataComputePseudoActivity(scip, consdata);
7126  else
7127  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7128  }
7129  else
7130  activity = consdataGetActivity(scip, consdata, sol);
7131 
7132  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7133  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7134  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7135  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7136 
7137  /* calculate absolute and relative bound violations */
7138  lhsviol = consdata->lhs - activity;
7139  rhsviol = activity - consdata->rhs;
7140 
7141  absviol = 0.0;
7142  relviol = 0.0;
7143  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7144  {
7145  absviol = lhsviol;
7146  relviol = SCIPrelDiff(consdata->lhs, activity);
7147  }
7148  else if( rhsviol > 0 )
7149  {
7150  absviol = rhsviol;
7151  relviol = SCIPrelDiff(activity, consdata->rhs);
7152  }
7153 
7154  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7155  * return infeasible for safety
7156  */
7157  if( activity == SCIP_INVALID ) /*lint !e777*/
7158  {
7159  assert(sol == NULL);
7160  *violated = TRUE;
7161 
7162  /* set violation of invalid pseudo solutions */
7163  absviol = SCIP_INVALID;
7164  relviol = SCIP_INVALID;
7165 
7166  /* reset constraint age since we are in enforcement */
7167  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7168  }
7169  /* check with relative tolerances (the default) */
7170  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7171  {
7172  /* the "normal" check: one of the two sides is violated */
7173  if( !checkrelmaxabs )
7174  {
7175  *violated = TRUE;
7176 
7177  /* only reset constraint age if we are in enforcement */
7178  if( sol == NULL )
7179  {
7180  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7181  }
7182  }
7183  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7184  * small compared to the absolute values occurring in the activity
7185  */
7186  else
7187  {
7188  SCIP_Real maxabs;
7189  SCIP_Real coef;
7190  SCIP_Real absval;
7191  SCIP_Real solval;
7192  int v;
7193 
7194  maxabs = 1.0;
7195 
7196  /* compute maximum absolute value */
7197  for( v = 0; v < consdata->nvars; ++v )
7198  {
7199  if( consdata->vals != NULL )
7200  {
7201  coef = consdata->vals[v];
7202  }
7203  else
7204  coef = 1.0;
7205 
7206  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7207  absval = REALABS( coef * solval );
7208  maxabs = MAX( maxabs, absval );
7209  }
7210 
7211  /* regard left hand side, first */
7212  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7213  {
7214  /* check whether violation is random noise */
7215  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7216  {
7217  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7218  consdata->lhs - activity, maxabs);
7219  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7220 
7221  /* only increase constraint age if we are in enforcement */
7222  if( sol == NULL )
7223  {
7224  SCIP_CALL( SCIPincConsAge(scip, cons) );
7225  }
7226  }
7227  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7228  else if( SCIPisZero(scip, consdata->lhs) )
7229  {
7230  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7231  {
7232  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7233  consdata->lhs - activity, maxabs);
7234  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7235 
7236  /* only increase constraint age if we are in enforcement */
7237  if( sol == NULL )
7238  {
7239  SCIP_CALL( SCIPincConsAge(scip, cons) );
7240  }
7241  }
7242  else
7243  {
7244  *violated = TRUE;
7245 
7246  /* only reset constraint age if we are in enforcement */
7247  if( sol == NULL )
7248  {
7249  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7250  }
7251  }
7252  }
7253  else
7254  {
7255  *violated = TRUE;
7256 
7257  /* only reset constraint age if we are in enforcement */
7258  if( sol == NULL )
7259  {
7260  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7261  }
7262  }
7263  }
7264 
7265  /* now regard right hand side */
7266  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7267  {
7268  /* check whether violation is random noise */
7269  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7270  {
7271  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7272  activity - consdata->rhs, maxabs);
7273  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7274 
7275  /* only increase constraint age if we are in enforcement */
7276  if( sol == NULL )
7277  {
7278  SCIP_CALL( SCIPincConsAge(scip, cons) );
7279  }
7280  }
7281  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7282  else if( SCIPisZero(scip, consdata->rhs) )
7283  {
7284  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7285  {
7286  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7287  activity - consdata->rhs, maxabs);
7288  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7289 
7290  /* only increase constraint age if we are in enforcement */
7291  if( sol == NULL )
7292  {
7293  SCIP_CALL( SCIPincConsAge(scip, cons) );
7294  }
7295  }
7296  else
7297  {
7298  *violated = TRUE;
7299 
7300  /* only reset constraint age if we are in enforcement */
7301  if( sol == NULL )
7302  {
7303  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7304  }
7305  }
7306  }
7307  else
7308  {
7309  *violated = TRUE;
7310 
7311  /* only reset constraint age if we are in enforcement */
7312  if( sol == NULL )
7313  {
7314  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7315  }
7316  }
7317  }
7318  }
7319  }
7320  /* check with absolute tolerances */
7321  else if( consdata->checkabsolute &&
7322  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7323  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7324  {
7325  *violated = TRUE;
7326 
7327  /* only reset constraint age if we are in enforcement */
7328  if( sol == NULL )
7329  {
7330  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7331  }
7332  }
7333  else
7334  {
7335  /* only increase constraint age if we are in enforcement */
7336  if( sol == NULL )
7337  {
7338  SCIP_CALL( SCIPincConsAge(scip, cons) );
7339  }
7340  }
7341 
7342  /* update absolute and relative violation of the solution */
7343  if( sol != NULL )
7344  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7345 
7346  return SCIP_OKAY;
7347 }
7348 
7349 /** creates an LP row in a linear constraint data */
7350 static
7352  SCIP* scip, /**< SCIP data structure */
7353  SCIP_CONS* cons /**< linear constraint */
7354  )
7355 {
7356  SCIP_CONSDATA* consdata;
7357 
7358  assert(scip != NULL);
7359  assert(cons != NULL);
7360 
7361  consdata = SCIPconsGetData(cons);
7362  assert(consdata != NULL);
7363  assert(consdata->row == NULL);
7364 
7365  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7367 
7368  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7369 
7370  return SCIP_OKAY;
7371 }
7372 
7373 /** adds linear constraint as cut to the LP */
7374 static
7376  SCIP* scip, /**< SCIP data structure */
7377  SCIP_CONS* cons, /**< linear constraint */
7378  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7379  )
7380 {
7381  SCIP_CONSDATA* consdata;
7382 
7383  assert(scip != NULL);
7384  assert(cons != NULL);
7385 
7386  consdata = SCIPconsGetData(cons);
7387  assert(consdata != NULL);
7388 
7389  if( consdata->row == NULL )
7390  {
7391  /* convert consdata object into LP row */
7392  SCIP_CALL( createRow(scip, cons) );
7393  }
7394  assert(consdata->row != NULL);
7395 
7396  if( consdata->nvars == 0 )
7397  {
7398  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7399  }
7400 
7401  /* insert LP row as cut */
7402  if( !SCIProwIsInLP(consdata->row) )
7403  {
7404  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7405  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7406  /* if presolving is turned off, the row might be trivial */
7407  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7408  {
7409  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7410  }
7411 #ifndef NDEBUG
7412  else
7413  {
7414  int pr;
7415  int cr;
7416  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7417  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7418  assert( pr == 0 || cr == 0 );
7419  }
7420 #endif
7421  }
7422 
7423  return SCIP_OKAY;
7424 }
7425 
7426 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7427 static
7429  SCIP* scip, /**< SCIP data structure */
7430  SCIP_CONS* cons, /**< linear constraint */
7431  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7432  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7433  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7434  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7435  * the ones with non-zero dual value? */
7436  int* ncuts, /**< pointer to add up the number of found cuts */
7437  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7438  )
7439 {
7440  SCIP_CONSDATA* consdata;
7441  SCIP_Bool violated;
7442  int oldncuts;
7443 
7444  assert(scip != NULL);
7445  assert(conshdlrdata != NULL);
7446  assert(cons != NULL);
7447  assert(cutoff != NULL);
7448 
7449  consdata = SCIPconsGetData(cons);
7450  assert(ncuts != NULL);
7451  assert(consdata != NULL);
7452 
7453  oldncuts = *ncuts;
7454  *cutoff = FALSE;
7455 
7456  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7457 
7458  if( violated )
7459  {
7460  /* insert LP row as cut */
7461  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7462  (*ncuts)++;
7463  }
7464  else if( !SCIPconsIsModifiable(cons) && separatecards )
7465  {
7466  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7467  if( !separateall && sol == NULL )
7468  {
7469  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7470  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7471  {
7472  SCIP_Real dualsol;
7473 
7474  dualsol = SCIProwGetDualsol(consdata->row);
7475  if( SCIPisFeasNegative(scip, dualsol) )
7476  {
7477  if( !SCIPisInfinity(scip, consdata->rhs) )
7478  {
7479  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7480  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7481  }
7482  }
7483  else if( SCIPisFeasPositive(scip, dualsol) )
7484  {
7485  if( !SCIPisInfinity(scip, -consdata->lhs) )
7486  {
7487  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7488  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7489  }
7490  }
7491  }
7492  }
7493  else
7494  {
7495  if( !SCIPisInfinity(scip, consdata->rhs) )
7496  {
7497  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7498  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7499  }
7500  if( !SCIPisInfinity(scip, -consdata->lhs) )
7501  {
7502  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7503  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7504  }
7505  }
7506  }
7507 
7508  if( *ncuts > oldncuts )
7509  {
7510  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7511  }
7512 
7513  return SCIP_OKAY;
7514 }
7515 
7516 /** propagation method for linear constraints */
7517 static
7519  SCIP* scip, /**< SCIP data structure */
7520  SCIP_CONS* cons, /**< linear constraint */
7521  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7522  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7523  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7524  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7525  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7526  int* nchgbds /**< pointer to count the total number of tightened bounds */
7527  )
7528 {
7529  SCIP_CONSDATA* consdata;
7530  SCIP_Real minactivity;
7531  SCIP_Real maxactivity;
7532  SCIP_Bool minactisrelax;
7533  SCIP_Bool maxactisrelax;
7534 
7535  assert(scip != NULL);
7536  assert(cons != NULL);
7537  assert(cutoff != NULL);
7538  assert(nchgbds != NULL);
7539 
7540  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7541 
7542  consdata = SCIPconsGetData(cons);
7543  assert(consdata != NULL);
7544 
7545  if( consdata->eventdata == NULL )
7546  {
7547  SCIP_CONSHDLR* conshdlr;
7548  SCIP_CONSHDLRDATA* conshdlrdata;
7549 
7550  conshdlr = SCIPconsGetHdlr(cons);
7551  assert(conshdlr != NULL);
7552 
7553  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7554  assert(conshdlrdata != NULL);
7555 
7556  /* catch bound change events of variables */
7557  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7558  assert(consdata->eventdata != NULL);
7559  }
7560 
7561  *cutoff = FALSE;
7562 
7563  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7564  if( !SCIPconsIsModifiable(cons) )
7565  {
7566  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7567  if( !SCIPinRepropagation(scip) )
7568  {
7569  SCIP_CALL( SCIPincConsAge(scip, cons) );
7570  }
7571 
7572  /* tighten the variable's bounds */
7573  if( tightenbounds )
7574  {
7575  int oldnchgbds;
7576 
7577  oldnchgbds = *nchgbds;
7578 
7579  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7580 
7581  if( *nchgbds > oldnchgbds )
7582  {
7583  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7584  }
7585  }
7586 
7587  /* propagate ranged rows */
7588  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7589  {
7590  int nfixedvars;
7591  int naddconss;
7592  /* cppcheck-suppress unassignedVariable */
7593  int oldnchgbds;
7594 
7595  nfixedvars = 0;
7596  naddconss = 0;
7597  SCIPdebug( oldnchgbds = *nchgbds; )
7598 
7599  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7600 
7601  if( *cutoff )
7602  {
7603  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7604  }
7605  else
7606  {
7607  SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars);
7608  }
7609 
7610  if( nfixedvars > 0 )
7611  *nchgbds += 2*nfixedvars;
7612  }
7613 
7614  /* check constraint for infeasibility and redundancy */
7615  if( !(*cutoff) )
7616  {
7617  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7618 
7619  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7620  {
7621  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7622  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7623 
7624  /* analyze conflict */
7625  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7626 
7627  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7628  *cutoff = TRUE;
7629  }
7630  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7631  {
7632  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7633  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7634 
7635  /* analyze conflict */
7636  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7637 
7638  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7639  *cutoff = TRUE;
7640  }
7641  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7642  {
7643  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7644  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7645 
7646  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7647  if( consdata->nvars > 0 )
7648  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7649  else
7650  SCIP_CALL( SCIPdelCons(scip, cons) );
7651  }
7652  }
7653  }
7654 
7655  return SCIP_OKAY;
7656 }
7657 
7658 
7659 /*
7660  * Presolving methods
7661  */
7662 
7663 /** converts all variables with fixed domain into FIXED variables */
7664 static
7666  SCIP* scip, /**< SCIP data structure */
7667  SCIP_CONS* cons, /**< linear constraint */
7668  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7669  int* nfixedvars /**< pointer to count the total number of fixed variables */
7670  )
7671 {
7672  SCIP_CONSDATA* consdata;
7673  SCIP_VAR* var;
7674  SCIP_VARSTATUS varstatus;
7675  SCIP_Real lb;
7676  SCIP_Real ub;
7677  SCIP_Bool fixed;
7678  SCIP_Bool infeasible;
7679  int v;
7680 
7681  assert(scip != NULL);
7682  assert(cons != NULL);
7683  assert(cutoff != NULL);
7684  assert(nfixedvars != NULL);
7685 
7686  consdata = SCIPconsGetData(cons);
7687  assert(consdata != NULL);
7688 
7689  for( v = 0; v < consdata->nvars; ++v )
7690  {
7691  assert(consdata->vars != NULL);
7692  var = consdata->vars[v];
7693  varstatus = SCIPvarGetStatus(var);
7694 
7695  if( varstatus != SCIP_VARSTATUS_FIXED )
7696  {
7697  lb = SCIPvarGetLbGlobal(var);
7698  ub = SCIPvarGetUbGlobal(var);
7699  if( SCIPisEQ(scip, lb, ub) )
7700  {
7701  SCIP_Real fixval;
7702 
7703  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7704  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7705  SCIPvarGetName(var), lb, ub, fixval);
7706  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7707  if( infeasible )
7708  {
7709  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7710  *cutoff = TRUE;
7711  return SCIP_OKAY;
7712  }
7713  if( fixed )
7714  (*nfixedvars)++;
7715  }
7716  }
7717  }
7718 
7719  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7720 
7721  if( infeasible )
7722  {
7723  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7724  *cutoff = TRUE;
7725  return SCIP_OKAY;
7726  }
7727 
7728  assert(consdata->removedfixings);
7729 
7730  return SCIP_OKAY;
7731 }
7732 
7733 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7734 
7735 /** extracts cliques of the constraint and adds them to SCIP
7736  *
7737  * The following clique extraction mechanism are implemeneted
7738  *
7739  * 1. collect binary variables and sort them in non increasing order, then
7740  *
7741  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7742  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7743  * condition
7744  *
7745  * minactivity + vals[i] + vals[i+1] > rhs
7746  *
7747  * and also add the binary to binary implication also for non-successive variables for which the same argument
7748  * holds
7749  *
7750  * minactivity + vals[i] + vals[j] > rhs
7751  *
7752  * 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
7753  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7754  *
7755  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7756  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7757  * condition
7758  *
7759  * maxactivity + vals[i] + vals[i-1] < lhs
7760  *
7761  * and also add the binary to binary implication also for non-successive variables for which the same argument
7762  * holds
7763  *
7764  * maxactivity + vals[i] + vals[j] < lhs
7765  *
7766  * e.g. you could multiply the above example by -1
7767  *
7768  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7769  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7770  * condition
7771  *
7772  * minactivity - vals[i] - vals[i-1] > rhs
7773  *
7774  * and also add the binary to binary implication also for non-successive variables for which the
7775  * same argument holds
7776  *
7777  * minactivity - vals[i] - vals[j] > rhs
7778  *
7779  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7780  * implication x1 = 0 => x3 = 1
7781  *
7782  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7783  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7784  * condition
7785  *
7786  * maxactivity - vals[i] - vals[i+1] < lhs
7787  *
7788  * and also add the binary to binary implication also for non-successive variables for which the same argument
7789  * holds
7790  *
7791  * maxactivity - vals[i] - vals[j] < lhs
7792  *
7793  * e.g. you could multiply the above example by -1
7794  *
7795  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7796  * as clique, (this part is done at the end of the method)
7797  *
7798  */
7799 static
7801  SCIP* scip, /**< SCIP data structure */
7802  SCIP_CONS* cons, /**< linear constraint */
7803  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7804  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7805  int* nfixedvars, /**< pointer to count number of fixed variables */
7806  int* nchgbds, /**< pointer to count the total number of tightened bounds */
7807  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7808  )
7809 {
7810  SCIP_VAR** vars;
7811  SCIP_Real* vals;
7812  SCIP_CONSDATA* consdata;
7813  SCIP_Bool lhsclique;
7814  SCIP_Bool rhsclique;
7815  SCIP_Bool finitelhs;
7816  SCIP_Bool finiterhs;
7817  SCIP_Bool finiteminact;
7818  SCIP_Bool finitemaxact;
7819  SCIP_Bool finitenegminact;
7820  SCIP_Bool finitenegmaxact;
7821  SCIP_Bool finiteposminact;
7822  SCIP_Bool finiteposmaxact;
7823  SCIP_Bool infeasible;
7824  SCIP_Bool stopped;
7825  int cliquenonzerosadded;
7826  int v;
7827  int i;
7828  int nposcoefs;
7829  int nnegcoefs;
7830  int nvars;
7831 
7832  assert(scip != NULL);
7833  assert(cons != NULL);
7834  assert(nfixedvars != NULL);
7835  assert(nchgbds != NULL);
7836  assert(cutoff != NULL);
7837  assert(!SCIPconsIsDeleted(cons));
7838 
7839  consdata = SCIPconsGetData(cons);
7840  assert(consdata != NULL);
7841 
7842  if( consdata->nvars < 2 )
7843  return SCIP_OKAY;
7844 
7845  /* add implications if posibble
7846  *
7847  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7848  * maximal absolute contribution and also only if this variable would force all other variables to their bound
7849  * corresponding to the global minimal activity of the constraint
7850  */
7851  if( !consdata->implsadded )
7852  {
7853  /* sort variables by variable type */
7854  SCIP_CALL( consdataSort(scip, consdata) );
7855 
7856  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7857  * up front, might change sorting correspondingly
7858  */
7859  /* fast abort if no binaries exist */
7860  if( !SCIPvarIsBinary(consdata->vars[0]) )
7861  return SCIP_OKAY;
7862 
7863  nvars = consdata->nvars;
7864  vars = consdata->vars;
7865  vals = consdata->vals;
7866 
7867  /* recompute activities if needed */
7868  if( !consdata->validactivities )
7869  consdataCalcActivities(scip, consdata);
7870  assert(consdata->validactivities);
7871 
7872  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7873  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7874  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7875  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7876  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7877  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7878  finiteminact = (finitenegminact && finiteposminact);
7879  finitemaxact = (finitenegmaxact && finiteposmaxact);
7880 
7881  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7882  {
7883  SCIP_Real maxabscontrib = -1.0;
7884  SCIP_Bool posval = FALSE;
7885  SCIP_Bool allbinary = TRUE;
7886  int oldnchgbds = *nchgbds;
7887  int nbdchgs = 0;
7888  int nimpls = 0;
7889  int position = -1;
7890 
7891  /* we need a valid minimal/maximal activity to add cliques */
7892  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
7893  {
7894  consdataRecomputeGlbMinactivity(scip, consdata);
7895  assert(consdata->validglbminact);
7896  }
7897 
7898  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
7899  {
7900  consdataRecomputeGlbMaxactivity(scip, consdata);
7901  assert(consdata->validglbmaxact);
7902  }
7903  assert(consdata->validglbminact || consdata->validglbmaxact);
7904 
7905  /* @todo extend this to local/constraint probing */
7906 
7907  /* determine maximal contribution to the activity */
7908  for( v = nvars - 1; v >= 0; --v )
7909  {
7910  if( SCIPvarIsBinary(vars[v]) )
7911  {
7912  if( vals[v] > 0 )
7913  {
7914  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
7915 
7916  if( value > maxabscontrib )
7917  {
7918  maxabscontrib = value;
7919  position = v;
7920  posval = TRUE;
7921  }
7922  }
7923  else
7924  {
7925  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
7926 
7927  value = REALABS(value);
7928 
7929  if( value > maxabscontrib )
7930  {
7931  maxabscontrib = value;
7932  position = v;
7933  posval = FALSE;
7934  }
7935  }
7936  }
7937  else
7938  allbinary = FALSE;
7939  }
7940  assert(0 <= position && position < nvars);
7941 
7942  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
7943  {
7944  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
7945  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7946  * implications
7947  */
7948  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
7949  {
7950  for( v = nvars - 1; v >= 0; --v )
7951  {
7952  /* binary to binary implications will be collected when extrating cliques */
7953  if( !SCIPvarIsBinary(vars[v]) )
7954  {
7955  if( v != position )
7956  {
7957  if( vals[v] > 0 )
7958  {
7959  /* add implications */
7960  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
7961  ++nimpls;
7962  *nchgbds += nbdchgs;
7963  }
7964  else
7965  {
7966  /* add implications */
7967  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
7968  ++nimpls;
7969  *nchgbds += nbdchgs;
7970  }
7971 
7972  if( infeasible )
7973  {
7974  *cutoff = TRUE;
7975  break;
7976  }
7977  }
7978  }
7979  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
7980  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
7981  break;
7982  }
7983  }
7984 
7985  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
7986  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7987  * implications
7988  */
7989  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
7990  {
7991  for( v = nvars - 1; v >= 0; --v )
7992  {
7993  /* binary to binary implications will be collected when extrating cliques */
7994  if( !SCIPvarIsBinary(vars[v]) )
7995  {
7996  if( v != position )
7997  {
7998  if( vals[v] > 0 )
7999  {
8000  /* add implications */
8001  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8002  ++nimpls;
8003  *nchgbds += nbdchgs;
8004  }
8005  else
8006  {
8007  /* add implications */
8008  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8009  ++nimpls;
8010  *nchgbds += nbdchgs;
8011  }
8012 
8013  if( infeasible )
8014  {
8015  *cutoff = TRUE;
8016  break;
8017  }
8018  }
8019  }
8020  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8021  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8022  break;
8023  }
8024  }
8025 
8026  /* did we find some implications */
8027  if( nimpls > 0 )
8028  {
8029  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8030 
8031  if( *cutoff )
8032  return SCIP_OKAY;
8033 
8034  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8035  if( *nchgbds - oldnchgbds > 0 )
8036  {
8037  /* check for fixed variables */
8038  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8039  if( *cutoff )
8040  return SCIP_OKAY;
8041 
8042  /* tighten variable's bounds */
8043  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8044  if( *cutoff )
8045  return SCIP_OKAY;
8046 
8047  /* check for fixed variables */
8048  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8049  if( *cutoff )
8050  return SCIP_OKAY;
8051  }
8052  }
8053  }
8054  }
8055 
8056  consdata->implsadded = TRUE;
8057  }
8058 
8059  /* check if we already added the cliques of this constraint */
8060  if( consdata->cliquesadded )
8061  return SCIP_OKAY;
8062 
8063  consdata->cliquesadded = TRUE;
8064  cliquenonzerosadded = 0;
8065  stopped = FALSE;
8066 
8067  /* sort variables by variable type */
8068  SCIP_CALL( consdataSort(scip, consdata) );
8069 
8070  nvars = consdata->nvars;
8071  vars = consdata->vars;
8072  vals = consdata->vals;
8073 
8074  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8075 
8076  /* recompute activities if needed */
8077  if( !consdata->validactivities )
8078  consdataCalcActivities(scip, consdata);
8079  assert(consdata->validactivities);
8080 
8081  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8082  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8083  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8084  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8085  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8086  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8087  finiteminact = (finitenegminact && finiteposminact);
8088  finitemaxact = (finitenegmaxact && finiteposmaxact);
8089 
8090  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8091  * information
8092  */
8093  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8094  {
8095  SCIP_VAR** binvars;
8096  SCIP_Real* binvarvals;
8097  int nposbinvars = 0;
8098  int nnegbinvars = 0;
8099  int allonebinary = 0;
8100 
8101  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8102  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8103 
8104  /* collect binary variables */
8105  for( i = 0; i < nvars; ++i )
8106  {
8107  if( SCIPvarIsBinary(vars[i]) )
8108  {
8109  assert(!SCIPisZero(scip, vals[i]));
8110 
8111  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8112  ++allonebinary;
8113 
8114  binvars[nposbinvars + nnegbinvars] = vars[i];
8115  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8116 
8117  if( SCIPisPositive(scip, vals[i]) )
8118  ++nposbinvars;
8119  else
8120  ++nnegbinvars;
8121 
8122  assert(nposbinvars + nnegbinvars <= nvars);
8123  }
8124  /* stop searching for binary variables, because the constraint data is sorted */
8125  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8126  break;
8127  }
8128  assert(nposbinvars + nnegbinvars <= nvars);
8129 
8130  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8131  * cliques
8132  */
8133  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8134  {
8135  SCIP_Real threshold;
8136  int oldnchgbds = *nchgbds;
8137  int nbdchgs;
8138  int jstart;
8139  int j;
8140 
8141  /* we need a valid minimal/maximal activity to add cliques */
8142  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8143  {
8144  consdataRecomputeGlbMinactivity(scip, consdata);
8145  assert(consdata->validglbminact);
8146  }
8147 
8148  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8149  {
8150  consdataRecomputeGlbMaxactivity(scip, consdata);
8151  assert(consdata->validglbmaxact);
8152  }
8153  assert(consdata->validglbminact || consdata->validglbmaxact);
8154 
8155  /* sort coefficients non-increasing to be faster in the clique search */
8156  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8157 
8158  /* case a) */
8159  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8160  {
8161  /* compute value that needs to be exceeded */
8162  threshold = consdata->rhs - consdata->glbminactivity;
8163 
8164  i = 0;
8165  j = i + 1;
8166 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8167  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8168  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
8169 #endif
8170  /* check if at least two variables are in a clique */
8171  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
8172  {
8173  ++j;
8174  /* check for extending the clique */
8175  while( j < nposbinvars )
8176  {
8177  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8178  break;
8179  ++j;
8180  }
8181  assert(j >= 2);
8182 
8183  /* add clique with at least two variables */
8184  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, FALSE, &infeasible, &nbdchgs) );
8185 
8186  if( infeasible )
8187  *cutoff = TRUE;
8188 
8189  *nchgbds += nbdchgs;
8190 
8191  cliquenonzerosadded += j;
8192  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8193  stopped = TRUE;
8194 
8195  /* exchange the last variable in the clique if possible and add all new ones */
8196  if( !stopped && !(*cutoff) && j < nposbinvars )
8197  {
8198  SCIP_VAR** clqvars;
8199  int lastfit = j - 2;
8200  assert(lastfit >= i);
8201 
8202  /* copy all 'main'-clique variables */
8203  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8204 
8205  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8206  while( lastfit >= i && j < nposbinvars )
8207  {
8208  /* check if two variables are in a clique */
8209  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8210  {
8211  clqvars[lastfit + 1] = binvars[j];
8212 
8213  /* add clique with at least two variables */
8214  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8215 
8216  if( infeasible )
8217  {
8218  *cutoff = TRUE;
8219  break;
8220  }
8221 
8222  *nchgbds += nbdchgs;
8223 
8224  cliquenonzerosadded += (lastfit - i + 2);
8225  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8226  {
8227  stopped = TRUE;
8228  break;
8229  }
8230 
8231  ++j;
8232  }
8233  else
8234  --lastfit;
8235  }
8236 
8237  SCIPfreeBufferArray(scip, &clqvars);
8238  }
8239  }
8240  }
8241 
8242  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8243  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8244  {
8245  /* check for fixed variables */
8246  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8247 
8248  if( !*cutoff )
8249  {
8250  /* tighten variable's bounds */
8251  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8252 
8253  if( !*cutoff )
8254  {
8255  /* check for fixed variables */
8256  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8257 
8258  if( !*cutoff )
8259  {
8260  /* sort variables by variable type */
8261  SCIP_CALL( consdataSort(scip, consdata) );
8262 
8263  /* recompute activities if needed */
8264  if( !consdata->validactivities )
8265  consdataCalcActivities(scip, consdata);
8266  assert(consdata->validactivities);
8267 
8268  nvars = consdata->nvars;
8269  vars = consdata->vars;
8270  vals = consdata->vals;
8271  nposbinvars = 0;
8272  nnegbinvars = 0;
8273  allonebinary = 0;
8274 
8275  /* update binary variables */
8276  for( i = 0; i < nvars; ++i )
8277  {
8278  if( SCIPvarIsBinary(vars[i]) )
8279  {
8280  assert(!SCIPisZero(scip, vals[i]));
8281 
8282  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8283  ++allonebinary;
8284 
8285  binvars[nposbinvars + nnegbinvars] = vars[i];
8286  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8287 
8288  if( SCIPisPositive(scip, vals[i]) )
8289  ++nposbinvars;
8290  else
8291  ++nnegbinvars;
8292 
8293  assert(nposbinvars + nnegbinvars <= nvars);
8294  }
8295  /* stop searching for binary variables, because the constraint data is sorted */
8296  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8297  break;
8298  }
8299  assert(nposbinvars + nnegbinvars <= nvars);
8300  }
8301  }
8302  }
8303 
8304  oldnchgbds = *nchgbds;
8305  }
8306 
8307  /* case b) */
8308  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8309  {
8310  /* compute value that needs to be deceeded */
8311  threshold = consdata->lhs - consdata->glbmaxactivity;
8312 
8313  i = nposbinvars + nnegbinvars - 1;
8314  j = i - 1;
8315 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8316  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8317  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8318 #endif
8319  /* check if two variables are in a clique */
8320  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8321  {
8322  --j;
8323  /* check for extending the clique */
8324  while( j >= nposbinvars )
8325  {
8326  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8327  break;
8328  --j;
8329  }
8330  jstart = j;
8331 
8332  assert(i - j >= 2);
8333  /* add clique with at least two variables */
8334  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8335 
8336  if( infeasible )
8337  *cutoff = TRUE;
8338 
8339  *nchgbds += nbdchgs;
8340 
8341  cliquenonzerosadded += (i - j);
8342  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8343  stopped = TRUE;
8344 
8345  /* exchange the last variable in the clique if possible and add all new ones */
8346  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8347  {
8348  SCIP_VAR** clqvars;
8349  int lastfit = jstart + 1;
8350  assert(lastfit < i);
8351 
8352  /* copy all 'main'-clique variables */
8353  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8354  ++lastfit;
8355 
8356  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8357  while( lastfit <= i && j >= nposbinvars )
8358  {
8359  /* check if two variables are in a clique */
8360  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8361  {
8362  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8363  clqvars[lastfit - jstart - 2] = binvars[j];
8364 
8365  assert(i - lastfit + 2 >= 2);
8366  /* add clique with at least two variables */
8367  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8368 
8369  if( infeasible )
8370  {
8371  *cutoff = TRUE;
8372  break;
8373  }
8374 
8375  *nchgbds += nbdchgs;
8376 
8377  cliquenonzerosadded += (i - lastfit + 2);
8378  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8379  {
8380  stopped = TRUE;
8381  break;
8382  }
8383 
8384  --j;
8385  }
8386  else
8387  ++lastfit;
8388  }
8389 
8390  SCIPfreeBufferArray(scip, &clqvars);
8391  }
8392  }
8393  }
8394 
8395  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8396  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8397  {
8398  /* check for fixed variables */
8399  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8400 
8401  if( !*cutoff )
8402  {
8403  /* tighten variable's bounds */
8404  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8405 
8406  if( !*cutoff )
8407  {
8408  /* check for fixed variables */
8409  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8410 
8411  if( !*cutoff )
8412  {
8413  /* sort variables by variable type */
8414  SCIP_CALL( consdataSort(scip, consdata) );
8415 
8416  /* recompute activities if needed */
8417  if( !consdata->validactivities )
8418  consdataCalcActivities(scip, consdata);
8419  assert(consdata->validactivities);
8420 
8421  nvars = consdata->nvars;
8422  vars = consdata->vars;
8423  vals = consdata->vals;
8424  nposbinvars = 0;
8425  nnegbinvars = 0;
8426  allonebinary = 0;
8427 
8428  /* update binary variables */
8429  for( i = 0; i < nvars; ++i )
8430  {
8431  if( SCIPvarIsBinary(vars[i]) )
8432  {
8433  assert(!SCIPisZero(scip, vals[i]));
8434 
8435  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8436  ++allonebinary;
8437 
8438  binvars[nposbinvars + nnegbinvars] = vars[i];
8439  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8440 
8441  if( SCIPisPositive(scip, vals[i]) )
8442  ++nposbinvars;
8443  else
8444  ++nnegbinvars;
8445 
8446  assert(nposbinvars + nnegbinvars <= nvars);
8447  }
8448  /* stop searching for binary variables, because the constraint data is sorted */
8449  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8450  break;
8451  }
8452  assert(nposbinvars + nnegbinvars <= nvars);
8453  }
8454  }
8455  }
8456 
8457  oldnchgbds = *nchgbds;
8458  }
8459 
8460  /* case c) */
8461  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8462  {
8463  SCIP_Bool* values;
8464 
8465  /* initialize clique values array for adding a negated clique */
8466  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8467  BMSclearMemoryArray(values, nnegbinvars);
8468 
8469  /* compute value that needs to be exceeded */
8470  threshold = consdata->rhs - consdata->glbminactivity;
8471 
8472  i = nposbinvars + nnegbinvars - 1;
8473  j = i - 1;
8474 
8475 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8476  /* check if the variable should not have already been fixed to one */
8477  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8478 #endif
8479 
8480  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8481  {
8482  --j;
8483  /* check for extending the clique */
8484  while( j >= nposbinvars )
8485  {
8486  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8487  break;
8488  --j;
8489  }
8490  jstart = j;
8491 
8492  assert(i - j >= 2);
8493  /* add negated clique with at least two variables */
8494  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8495 
8496  if( infeasible )
8497  *cutoff = TRUE;
8498 
8499  *nchgbds += nbdchgs;
8500 
8501  cliquenonzerosadded += (i - j);
8502  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8503  stopped = TRUE;
8504 
8505  /* exchange the last variable in the clique if possible and add all new ones */
8506  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8507  {
8508  SCIP_VAR** clqvars;
8509  int lastfit = j + 1;
8510  assert(lastfit < i);
8511 
8512  /* copy all 'main'-clique variables */
8513  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8514  ++lastfit;
8515 
8516  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8517  while( lastfit <= i && j >= nposbinvars )
8518  {
8519  /* check if two variables are in a negated clique */
8520  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8521  {
8522  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8523  clqvars[lastfit - jstart - 2] = binvars[j];
8524 
8525  assert(i - lastfit + 2 >= 2);
8526  /* add clique with at least two variables */
8527  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8528 
8529  if( infeasible )
8530  {
8531  *cutoff = TRUE;
8532  break;
8533  }
8534 
8535  *nchgbds += nbdchgs;
8536 
8537  cliquenonzerosadded += (i - lastfit + 2);
8538  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8539  {
8540  stopped = TRUE;
8541  break;
8542  }
8543 
8544  --j;
8545  }
8546  else
8547  ++lastfit;
8548  }
8549 
8550  SCIPfreeBufferArray(scip, &clqvars);
8551  }
8552  }
8553 
8554  SCIPfreeBufferArray(scip, &values);
8555  }
8556 
8557  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8558  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8559  {
8560  /* check for fixed variables */
8561  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8562 
8563  if( !*cutoff )
8564  {
8565  /* tighten variable's bounds */
8566  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8567 
8568  if( !*cutoff )
8569  {
8570  /* check for fixed variables */
8571  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8572 
8573  if( !*cutoff )
8574  {
8575  /* sort variables by variable type */
8576  SCIP_CALL( consdataSort(scip, consdata) );
8577 
8578  /* recompute activities if needed */
8579  if( !consdata->validactivities )
8580  consdataCalcActivities(scip, consdata);
8581  assert(consdata->validactivities);
8582 
8583  nvars = consdata->nvars;
8584  vars = consdata->vars;
8585  vals = consdata->vals;
8586  nposbinvars = 0;
8587  nnegbinvars = 0;
8588  allonebinary = 0;
8589 
8590  /* update binary variables */
8591  for( i = 0; i < nvars; ++i )
8592  {
8593  if( SCIPvarIsBinary(vars[i]) )
8594  {
8595  assert(!SCIPisZero(scip, vals[i]));
8596 
8597  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8598  ++allonebinary;
8599 
8600  binvars[nposbinvars + nnegbinvars] = vars[i];
8601  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8602 
8603  if( SCIPisPositive(scip, vals[i]) )
8604  ++nposbinvars;
8605  else
8606  ++nnegbinvars;
8607 
8608  assert(nposbinvars + nnegbinvars <= nvars);
8609  }
8610  /* stop searching for binary variables, because the constraint data is sorted */
8611  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8612  break;
8613  }
8614  assert(nposbinvars + nnegbinvars <= nvars);
8615  }
8616  }
8617  }
8618  }
8619 
8620  /* case d) */
8621  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8622  {
8623  SCIP_Bool* values;
8624 
8625  /* initialize clique values array for adding a negated clique */
8626  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8627  BMSclearMemoryArray(values, nposbinvars);
8628 
8629  /* compute value that needs to be exceeded */
8630  threshold = consdata->lhs - consdata->glbmaxactivity;
8631 
8632  i = 0;
8633  j = i + 1;
8634 
8635 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8636  /* check if the variable should not have already been fixed to one */
8637  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
8638 #endif
8639 
8640  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8641  {
8642  ++j;
8643  /* check for extending the clique */
8644  while( j < nposbinvars )
8645  {
8646  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8647  break;
8648  ++j;
8649  }
8650  assert(j >= 2);
8651 
8652  /* add negated clique with at least two variables */
8653  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, FALSE, &infeasible, &nbdchgs) );
8654 
8655  if( infeasible )
8656  *cutoff = TRUE;
8657 
8658  *nchgbds += nbdchgs;
8659 
8660  cliquenonzerosadded += j;
8661  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8662  stopped = TRUE;
8663 
8664  /* exchange the last variable in the clique if possible and add all new ones */
8665  if( !stopped && !(*cutoff) && j < nposbinvars )
8666  {
8667  SCIP_VAR** clqvars;
8668  int lastfit = j - 2;
8669  assert(lastfit >= i);
8670 
8671  /* copy all 'main'-clique variables */
8672  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8673 
8674  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8675  while( lastfit >= i && j < nposbinvars )
8676  {
8677  /* check if two variables are in a negated clique */
8678  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8679  {
8680  clqvars[lastfit + 1] = binvars[j];
8681 
8682  /* add clique with at least two variables */
8683  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8684 
8685  if( infeasible )
8686  {
8687  *cutoff = TRUE;
8688  break;
8689  }
8690 
8691  *nchgbds += nbdchgs;
8692 
8693  cliquenonzerosadded += (lastfit - i + 2);
8694  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8695  break;
8696 
8697  ++j;
8698  }
8699  else
8700  --lastfit;
8701  }
8702 
8703  SCIPfreeBufferArray(scip, &clqvars);
8704  }
8705  }
8706 
8707  SCIPfreeBufferArray(scip, &values);
8708  }
8709  }
8710 
8711  SCIPfreeBufferArray(scip, &binvarvals);
8712  SCIPfreeBufferArray(scip, &binvars);
8713 
8714  if( *cutoff )
8715  return SCIP_OKAY;
8716  }
8717 
8718  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8719 
8720  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8721  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8722  */
8723  nposcoefs = 0;
8724  nnegcoefs = 0;
8725  for( i = 0; i < nvars; ++i )
8726  {
8727  if( !SCIPvarIsBinary(vars[i]) )
8728  return SCIP_OKAY;
8729  else if( SCIPisEQ(scip, vals[i], +1.0) )
8730  nposcoefs++;
8731  else if( SCIPisEQ(scip, vals[i], -1.0) )
8732  nnegcoefs++;
8733  else
8734  return SCIP_OKAY;
8735  }
8736 
8737  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8738  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8739 
8740  if( lhsclique || rhsclique )
8741  {
8742  SCIP_Bool* values;
8743  int nbdchgs;
8744 
8745  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8746  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8747  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8748 
8749  for( i = 0; i < nvars; ++i )
8750  values[i] = (rhsclique == (vals[i] > 0.0));
8751 
8752  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8753 
8754  if( infeasible )
8755  *cutoff = TRUE;
8756 
8757  *nchgbds += nbdchgs;
8758  SCIPfreeBufferArray(scip, &values);
8759  }
8760 
8761  return SCIP_OKAY;
8762 }
8763 
8764 /** tightens left and right hand side of constraint due to integrality */
8765 static
8767  SCIP* scip, /**< SCIP data structure */
8768  SCIP_CONS* cons, /**< linear constraint */
8769  int* nchgsides /**< pointer to count number of side changes */
8770  )
8771 {
8772  SCIP_CONSDATA* consdata;
8773  SCIP_Bool integral;
8774  int i;
8775 
8776  assert(scip != NULL);
8777  assert(cons != NULL);
8778  assert(nchgsides != NULL);
8779 
8780  consdata = SCIPconsGetData(cons);
8781  assert(consdata != NULL);
8782 
8783  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8784  {
8785  integral = TRUE;
8786  for( i = 0; i < consdata->nvars && integral; ++i )
8787  {
8788  integral = SCIPisIntegral(scip, consdata->vals[i])
8789  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8790  }
8791  if( integral )
8792  {
8793  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8794  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8795  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8796  {
8797  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
8798  if( !consdata->upgraded )
8799  (*nchgsides)++;
8800  }
8801  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8802  {
8803  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
8804  if( !consdata->upgraded )
8805  (*nchgsides)++;
8806  }
8807  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8808  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8809  }
8810  }
8811 
8812  return SCIP_OKAY;
8813 }
8814 
8815 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8816  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8817  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8818  * (i) ai >= 0:
8819  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8820  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8821  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8822  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8823  * - change coefficients:
8824  * ai' := max(lhs - minact, maxact - rhs)
8825  * lhs' := lhs - (ai - ai')*li
8826  * rhs' := rhs - (ai - ai')*ui
8827  * (ii) ai < 0:
8828  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8829  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8830  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8831  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8832  * - change coefficients:
8833  * ai' := min(rhs - maxact, minact - lhs)
8834  * lhs' := lhs - (ai - ai')*ui
8835  * rhs' := rhs - (ai - ai')*li
8836  *
8837  * We further try to remove redundant variable from the constraint;
8838  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
8839  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8840  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
8841  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
8842  * 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
8843  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
8844  *
8845  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8846  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8847  */
8848 static
8850  SCIP* scip, /**< SCIP data structure */
8851  SCIP_CONS* cons, /**< linear constraint */
8852  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8853  int* nchgsides /**< pointer to count number of side changes */
8854  )
8855 {
8856  SCIP_CONSDATA* consdata;
8857  SCIP_VAR* var;
8858  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
8859  * activity, ignoring the coefficients contributing with infinite value */
8860  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
8861  * activity, ignoring the coefficients contributing with infinite value */
8862  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
8863  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
8864  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
8865  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
8866  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
8867  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
8868  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
8869  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
8870  SCIP_Real val;
8871  SCIP_Real newval;
8872  SCIP_Real newlhs;
8873  SCIP_Real newrhs;
8874  SCIP_Real lb;
8875  SCIP_Real ub;
8876  int i;
8877 
8878  assert(scip != NULL);
8879  assert(cons != NULL);
8880  assert(nchgcoefs != NULL);
8881  assert(nchgsides != NULL);
8882 
8883  consdata = SCIPconsGetData(cons);
8884  assert(consdata != NULL);
8885 
8886  /* @todo Is this still needed with automatic recomputation of activities? */
8887  /* if the maximal coefficient is too large, recompute the activities */
8888  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
8889  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
8890  {
8891  consdataRecomputeMinactivity(scip, consdata);
8892  consdataRecomputeMaxactivity(scip, consdata);
8893  }
8894 
8895  /* get the minimal and maximal activity of the constraint */
8896  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8897 
8898  minleftactivity = 0.0;
8899  maxleftactivity = 0.0;
8900 
8901  /* try to tighten each coefficient */
8902  i = 0;
8903  while( i < consdata->nvars )
8904  {
8905  var = consdata->vars[i];
8906 
8907  /* get coefficient and variable's bounds */
8908  lb = SCIPvarGetLbLocal(var);
8909  ub = SCIPvarGetUbLocal(var);
8910  val = consdata->vals[i];
8911  assert(!SCIPisZero(scip, val));
8912 
8913  /* check sign of coefficient */
8914  if( val >= 0.0 )
8915  {
8916  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
8918  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
8919  {
8920  /* change coefficients:
8921  * ai' := max(lhs - minact, maxact - rhs)
8922  * lhs' := lhs - (ai - ai')*li
8923  * rhs' := rhs - (ai - ai')*ui
8924  */
8925 
8926  lval = consdata->lhs - minactivity;
8927  rval = maxactivity - consdata->rhs;
8928 
8929  /* Try to avoid cancellation, if there are only two variables */
8930  if( consdata->nvars == 2 )
8931  {
8932  SCIP_Real otherval;
8933  otherval = consdata->vals[1-i];
8934 
8935  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
8936  {
8937  lval = consdata->lhs - val*lb;
8938  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
8939  }
8940 
8941  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
8942  {
8943  rval = val*ub - consdata->rhs;
8944  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
8945  }
8946  }
8947 
8948  newval = MAX(lval, rval);
8949  assert(SCIPisSumRelLE(scip, newval, val));
8950 
8951  /* Try to avoid cancellation in computation of lhs/rhs */
8952  newlhs = consdata->lhs - val * lb;
8953  newlhs += newval * lb;
8954  newrhs = consdata->rhs - val * ub;
8955  newrhs += newval * ub;
8956 
8957  if( !SCIPisSumRelEQ(scip, newval, val) )
8958  {
8959  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
8960  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
8961  minactivity, maxactivity, consdata->lhs, consdata->rhs);
8962 
8963  /* update the coefficient and the activity bounds */
8964  if( SCIPisZero(scip, newval) )
8965  {
8966  SCIP_CALL( delCoefPos(scip, cons, i) );
8967  i--;
8968  }
8969  else
8970  {
8971  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
8972  }
8973  (*nchgcoefs)++;
8974 
8975  /* get the new minimal and maximal activity of the constraint */
8976  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8977 
8978  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
8979  {
8980  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
8981 
8982  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8983  (*nchgsides)++;
8984  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
8985  }
8986 
8987  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
8988  {
8989  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
8990 
8991  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8992  (*nchgsides)++;
8993  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
8994  }
8995  }
8996  }
8997  else
8998  {
8999  if( !SCIPisInfinity(scip, -minleftactivity) )
9000  {
9001  assert(!SCIPisInfinity(scip, val));
9002  assert(!SCIPisInfinity(scip, lb));
9003  if( SCIPisInfinity(scip, -lb) )
9004  minleftactivity = -SCIPinfinity(scip);
9005  else
9006  minleftactivity += val * lb;
9007  }
9008 
9009  if( !SCIPisInfinity(scip, maxleftactivity) )
9010  {
9011  assert(!SCIPisInfinity(scip, val));
9012  assert(!SCIPisInfinity(scip, -ub));
9013  if( SCIPisInfinity(scip,ub) )
9014  maxleftactivity = SCIPinfinity(scip);
9015  else
9016  maxleftactivity += val * ub;
9017  }
9018  }
9019  }
9020  else
9021  {
9022  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9024  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9025  {
9026  /* change coefficients:
9027  * ai' := min(rhs - maxact, minact - lhs)
9028  * lhs' := lhs - (ai - ai')*ui
9029  * rhs' := rhs - (ai - ai')*li
9030  */
9031 
9032  lval = minactivity - consdata->lhs;
9033  rval = consdata->rhs - maxactivity;
9034 
9035  /* Try to avoid cancellation, if there are only two variables */
9036  if( consdata->nvars == 2 )
9037  {
9038  SCIP_Real otherval;
9039  otherval = consdata->vals[1-i];
9040 
9041  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9042  {
9043  lval = val*ub - consdata->lhs;
9044  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9045  }
9046 
9047  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9048  {
9049  rval = consdata->rhs - val*lb;
9050  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9051  }
9052  }
9053 
9054  newval = MIN(lval, rval);
9055  assert(SCIPisSumRelGE(scip, newval, val));
9056 
9057  /* Try to avoid cancellation in computation of lhs/rhs */
9058  newlhs = consdata->lhs - val * ub;
9059  newlhs += newval * ub;
9060  newrhs = consdata->rhs - val * lb;
9061  newrhs += newval * lb;
9062 
9063  if( !SCIPisSumRelEQ(scip, newval, val) )
9064  {
9065  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9066  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9067  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9068 
9069  /* update the coefficient and the activity bounds */
9070  if( SCIPisZero(scip, newval) )
9071  {
9072  SCIP_CALL( delCoefPos(scip, cons, i) );
9073  i--;
9074  }
9075  else
9076  {
9077  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9078  }
9079  (*nchgcoefs)++;
9080 
9081  /* get the new minimal and maximal activity of the constraint */
9082  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9083 
9084  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9085  {
9086  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9087 
9088  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9089  (*nchgsides)++;
9090  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9091  }
9092 
9093  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9094  {
9095  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9096 
9097  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9098  (*nchgsides)++;
9099  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9100  }
9101  }
9102  }
9103  else
9104  {
9105  if( !SCIPisInfinity(scip, -minleftactivity) )
9106  {
9107  assert(!SCIPisInfinity(scip, -val));
9108  assert(!SCIPisInfinity(scip, -ub));
9109  if( SCIPisInfinity(scip, ub) )
9110  minleftactivity = -SCIPinfinity(scip);
9111  else
9112  minleftactivity += val * ub;
9113  }
9114 
9115  if( !SCIPisInfinity(scip, maxleftactivity) )
9116  {
9117  assert(!SCIPisInfinity(scip, -val));
9118  assert(!SCIPisInfinity(scip, lb));
9119  if( SCIPisInfinity(scip, -lb) )
9120  maxleftactivity = SCIPinfinity(scip);
9121  else
9122  maxleftactivity += val * lb;
9123  }
9124  }
9125  }
9126  ++i;
9127  }
9128 
9129  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9130  minleftactivity, consdata->rhs);
9131  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9132  maxleftactivity, consdata->lhs);
9133 
9134  /* minleft == \infty ==> minactivity == \infty */
9135  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9136  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9137 
9138  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9139  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9140  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9141  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9142  */
9143  assert(!SCIPisInfinity(scip, minactivity));
9144  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9145  return SCIP_OKAY;
9146 
9147  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9148  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9149  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9150  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9151  */
9152  assert(!SCIPisInfinity(scip, -maxactivity));
9153  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9154  return SCIP_OKAY;
9155 
9156  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9157  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9158  */
9159  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9160  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9161 
9162  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9163  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9164  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9165  * they can be removed from the constraint.
9166  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9167  */
9168  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9169  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9170  {
9171  SCIP_Real minleftactivitypart;
9172  SCIP_Real maxleftactivitypart;
9173 
9174  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9175 
9176  /* try to remove redundant variables from constraint */
9177  i = 0;
9178  while( i < consdata->nvars )
9179  {
9180  var = consdata->vars[i];
9181  minleftactivitypart = 0.0;
9182  maxleftactivitypart = 0.0;
9183  lb = SCIPvarGetLbLocal(var);
9184  ub = SCIPvarGetUbLocal(var);
9185 
9186  /* get coefficient and variable's bounds */
9187  val = consdata->vals[i];
9188  assert(!SCIPisZero(scip, val));
9189 
9190  /* check sign of coefficient */
9191  if( val >= 0.0 )
9192  {
9193  /* negation of condition above in case of positive val */
9194  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9195  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9196  {
9197  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9198  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9199  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9200  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9201 
9202  minleftactivitypart = val * lb;
9203  maxleftactivitypart = val * ub;
9204 
9205  SCIP_CALL( delCoefPos(scip, cons, i) );
9206  i--;
9207 
9208  /* get the new minimal and maximal activity of the constraint */
9209  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9210 
9211  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9212  * huge contributions
9213  */
9214  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9215  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9216  }
9217  }
9218  else
9219  {
9220  /* negation of condition above in case of negative val */
9221  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9222  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9223  {
9224  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9225  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9226 
9227  minleftactivitypart = val * ub;
9228  maxleftactivitypart = val * lb;
9229 
9230  SCIP_CALL( delCoefPos(scip, cons, i) );
9231  i--;
9232 
9233  /* get the new minimal and maximal activity of the constraint */
9234  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9235 
9236  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9237  * huge contributions
9238  */
9239  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9240  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9241  }
9242  }
9243 
9244  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9245  * redundant variables could get deleted,
9246  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9247  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9248  * we would also delete y2 and as a result we would have gotten infeasibility */
9249  /* adjust lhs and right hand side */
9250  newlhs = consdata->lhs - minleftactivitypart;
9251  newrhs = consdata->rhs - maxleftactivitypart;
9252 
9253  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9254  {
9255  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9256  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9257  ++(*nchgsides);
9258  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9259  }
9260  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9261  {
9262  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9263  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9264  ++(*nchgsides);
9265  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9266  }
9267  ++i;
9268  }
9269  }
9270 
9271  return SCIP_OKAY;
9272 }
9273 
9274 /* processes equality with only one variable by fixing the variable and deleting the constraint */
9275 static
9277  SCIP* scip, /**< SCIP data structure */
9278  SCIP_CONS* cons, /**< linear constraint */
9279  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9280  int* nfixedvars, /**< pointer to count number of fixed variables */
9281  int* ndelconss /**< pointer to count number of deleted constraints */
9282  )
9283 {
9284  SCIP_CONSDATA* consdata;
9285  SCIP_VAR* var;
9286  SCIP_Real val;
9287  SCIP_Real fixval;
9288  SCIP_Bool infeasible;
9289  SCIP_Bool fixed;
9290 
9291  assert(scip != NULL);
9292  assert(cons != NULL);
9293  assert(cutoff != NULL);
9294  assert(nfixedvars != NULL);
9295  assert(ndelconss != NULL);
9296 
9297  consdata = SCIPconsGetData(cons);
9298  assert(consdata != NULL);
9299  assert(consdata->nvars == 1);
9300  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9301 
9302  /* calculate the value to fix the variable to */
9303  var = consdata->vars[0];
9304  val = consdata->vals[0];
9305  assert(!SCIPisZero(scip, val));
9306  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9307  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9308  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9309  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9310 
9311  /* fix variable */
9312  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9313  if( infeasible )
9314  {
9315  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9316  *cutoff = TRUE;
9317  return SCIP_OKAY;
9318  }
9319  if( fixed )
9320  (*nfixedvars)++;
9321 
9322  /* disable constraint */
9323  SCIP_CALL( SCIPdelCons(scip, cons) );
9324  if( !consdata->upgraded )
9325  (*ndelconss)++;
9326 
9327  return SCIP_OKAY;
9328 }
9329 
9330 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9331 static
9333  SCIP* scip, /**< SCIP data structure */
9334  SCIP_CONS* cons, /**< linear constraint */
9335  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9336  int* naggrvars, /**< pointer to count number of aggregated variables */
9337  int* ndelconss /**< pointer to count number of deleted constraints */
9338  )
9339 {
9340  SCIP_CONSDATA* consdata;
9341  SCIP_Bool infeasible;
9342  SCIP_Bool redundant;
9343  SCIP_Bool aggregated;
9344 
9345  assert(scip != NULL);
9346  assert(cons != NULL);
9347  assert(cutoff != NULL);
9348  assert(naggrvars != NULL);
9349  assert(ndelconss != NULL);
9350 
9351  consdata = SCIPconsGetData(cons);
9352  assert(consdata != NULL);
9353  assert(consdata->nvars == 2);
9354  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9355 
9356  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9357  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9358  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9359 
9360  /* aggregate the equality */
9361  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9362  consdata->rhs, &infeasible, &redundant, &aggregated) );
9363 
9364  /* check for infeasibility of aggregation */
9365  if( infeasible )
9366  {
9367  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9368  *cutoff = TRUE;
9369  return SCIP_OKAY;
9370  }
9371 
9372  /* count the aggregation */
9373  if( aggregated )
9374  (*naggrvars)++;
9375 
9376  /* delete the constraint, if it is redundant */
9377  if( redundant )
9378  {
9379  SCIP_CALL( SCIPdelCons(scip, cons) );
9380 
9381  if( !consdata->upgraded )
9382  (*ndelconss)++;
9383  }
9384 
9385  return SCIP_OKAY;
9386 }
9387 
9388 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9389 static
9391  SCIP* scip, /**< SCIP data structure */
9392  SCIP_CONSDATA* consdata, /**< linear constraint data */
9393  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9394  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9395  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9396  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9397  )
9398 {
9399  SCIP_Real slackvarlb;
9400  SCIP_Real slackvarub;
9401 
9402  assert(scip != NULL);
9403  assert(consdata != NULL);
9404  assert(newlhs != NULL);
9405  assert(newrhs != NULL);
9406  assert(!SCIPisInfinity(scip, -consdata->lhs));
9407  assert(!SCIPisInfinity(scip, consdata->rhs));
9408 
9409  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9410  slackvarub = SCIPvarGetUbGlobal(slackvar);
9411  if( slackcoef > 0.0 )
9412  {
9413  if( SCIPisInfinity(scip, -slackvarlb) )
9414  *newrhs = SCIPinfinity(scip);
9415  else
9416  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9417  if( SCIPisInfinity(scip, slackvarub) )
9418  *newlhs = -SCIPinfinity(scip);
9419  else
9420  *newlhs = consdata->lhs - slackcoef * slackvarub;
9421  }
9422  else
9423  {
9424  if( SCIPisInfinity(scip, -slackvarlb) )
9425  *newlhs = -SCIPinfinity(scip);
9426  else
9427  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9428  if( SCIPisInfinity(scip, slackvarub) )
9429  *newrhs = SCIPinfinity(scip);
9430  else
9431  *newrhs = consdata->lhs - slackcoef * slackvarub;
9432  }
9433  assert(SCIPisLE(scip, *newlhs, *newrhs));
9434 }
9435 
9436 #define MAXMULTIAGGRQUOTIENT 1e+03
9437 
9438 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9439  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9440  * is implicitly integral by this constraint
9441  *
9442  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9443  * can help.
9444  */
9445 static
9447  SCIP* scip, /**< SCIP data structure */
9448  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9449  SCIP_CONS* cons, /**< linear constraint */
9450  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9451  int* naggrvars, /**< pointer to count number of aggregated variables */
9452  int* ndelconss /**< pointer to count number of deleted constraints */
9453  )
9454 {
9455  SCIP_CONSDATA* consdata;
9456  SCIP_VAR** vars;
9457  SCIP_Real* vals;
9458  SCIP_VARTYPE bestslacktype;
9459  SCIP_VARTYPE slacktype;
9460  SCIP_Real lhs;
9461  SCIP_Real rhs;
9462  SCIP_Real bestslackdomrng;
9463  SCIP_Real minabsval;
9464  SCIP_Real maxabsval;
9465  SCIP_Bool bestremovescons;
9466  SCIP_Bool coefszeroone;
9467  SCIP_Bool coefsintegral;
9468  SCIP_Bool varsintegral;
9469  SCIP_Bool infeasible;
9470  SCIP_Bool samevar;
9471  int supinf; /* counter for infinite contributions to the supremum of a possible
9472  * multi-aggregation
9473  */
9474  int infinf; /* counter for infinite contributions to the infimum of a possible
9475  * multi-aggregation
9476  */
9477  int maxnlocksstay;
9478  int maxnlocksremove;
9479  int bestslackpos;
9480  int bestnlocks;
9481  int ncontvars;
9482  int contvarpos;
9483  int nintvars;
9484  int nimplvars;
9485  int intvarpos;
9486  int v;
9487 
9488  assert(scip != NULL);
9489  assert(cons != NULL);
9490  assert(cutoff != NULL);
9491  assert(naggrvars != NULL);
9492 
9493  consdata = SCIPconsGetData(cons);
9494  assert(consdata != NULL);
9495  assert(consdata->nvars > 2);
9496  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9497 
9498  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9499 
9500  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9501  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9502  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9503  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9504  */
9505  lhs = consdata->lhs;
9506  rhs = consdata->rhs;
9507  maxnlocksstay = 0;
9508  if( consdata->nvars == 3 )
9509  {
9510  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9511  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9512  */
9513  maxnlocksremove = 3;
9514  }
9515  else if( consdata->nvars == 4 )
9516  {
9517  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9518  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9519  */
9520  maxnlocksremove = 2;
9521  }
9522  else
9523  {
9524  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9525  maxnlocksremove = 1;
9526  }
9527 
9528  /* the locks on this constraint can be ignored */
9529  if( SCIPconsIsChecked(cons) )
9530  {
9531  if( !SCIPisInfinity(scip, -lhs) )
9532  {
9533  maxnlocksstay++;
9534  maxnlocksremove++;
9535  }
9536  if( !SCIPisInfinity(scip, rhs) )
9537  {
9538  maxnlocksstay++;
9539  maxnlocksremove++;
9540  }
9541  }
9542 
9543  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9544  vars = consdata->vars;
9545  vals = consdata->vals;
9546  bestslackpos = -1;
9547  bestslacktype = SCIP_VARTYPE_BINARY;
9548  bestnlocks = INT_MAX;
9549  bestremovescons = FALSE;
9550  bestslackdomrng = 0.0;
9551  coefszeroone = TRUE;
9552  coefsintegral = TRUE;
9553  varsintegral = TRUE;
9554  ncontvars = 0;
9555  contvarpos = -1;
9556  nintvars = 0;
9557  nimplvars = 0;
9558  intvarpos = -1;
9559  minabsval = SCIPinfinity(scip);
9560  maxabsval = -1.0;
9561  for( v = 0; v < consdata->nvars; ++v )
9562  {
9563  SCIP_VAR* var;
9564  SCIP_Real val;
9565  SCIP_Real absval;
9566  SCIP_Real varlb;
9567  SCIP_Real varub;
9568  SCIP_Bool iscont;
9569  int nlocks;
9570 
9571  assert(vars != NULL);
9572  assert(vals != NULL);
9573 
9574  var = vars[v];
9575  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDown(var) >= 1); /* because variable is locked in this equality */
9576  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUp(var) >= 1);
9577  varlb = SCIPvarGetLbGlobal(var);
9578  varub = SCIPvarGetUbGlobal(var);
9579 
9580  val = vals[v];
9581  absval = REALABS(val);
9582  assert(SCIPisPositive(scip, absval));
9583 
9584  /* calculate minimal and maximal absolute value */
9585  if( absval < minabsval )
9586  minabsval = absval;
9587  if( absval > maxabsval )
9588  maxabsval = absval;
9589 
9590  /* do not try to multi aggregate, when numerical bad */
9591  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
9592  return SCIP_OKAY;
9593 
9594  slacktype = SCIPvarGetType(var);
9595  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9596  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9597  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9598  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9599 
9600  /* update candidates for continuous -> implint and integer -> implint conversion */
9601  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9602  {
9603  ncontvars++;
9604  contvarpos = v;
9605  }
9606  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9607  {
9608  ++nimplvars;
9609  }
9610  else if( slacktype == SCIP_VARTYPE_INTEGER )
9611  {
9612  nintvars++;
9613  intvarpos = v;
9614  }
9615 
9616  /* check, if variable is already fixed or aggregated */
9617  if( !SCIPvarIsActive(var) )
9618  continue;
9619 
9620  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9621  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
9622 
9623  if( nlocks > maxnlocksremove )
9624  continue;
9625 
9626  /* check, if variable can be used as a slack variable */
9627  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9628  !SCIPdoNotMultaggrVar(scip, var) )
9629  {
9630  SCIP_Bool better;
9631  SCIP_Bool equal;
9632  SCIP_Real slackdomrng;
9633 
9634  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9635  slackdomrng = SCIPinfinity(scip);
9636  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9637  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9638  return SCIP_OKAY;
9639  else
9640  {
9641  slackdomrng = (varub - varlb)*absval;
9642  assert(!SCIPisInfinity(scip, slackdomrng));
9643  }
9644  equal = FALSE;
9645  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9646  if( !better && slacktype == bestslacktype )
9647  {
9648  better = (nlocks < bestnlocks);
9649  if( nlocks == bestnlocks && !bestremovescons )
9650  {
9651  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9652  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9653  }
9654  }
9655 
9656  if( better || equal )
9657  {
9658  SCIP_Real minresactivity;
9659  SCIP_Real maxresactivity;
9660  SCIP_Real newlhs;
9661  SCIP_Real newrhs;
9662  SCIP_Bool removescons;
9663  SCIP_Bool minisrelax;
9664  SCIP_Bool maxisrelax;
9665  SCIP_Bool isminsettoinfinity;
9666  SCIP_Bool ismaxsettoinfinity;
9667 
9668  /* check if the constraint becomes redundant after multi-aggregation */
9669  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9670  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9671 
9672  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9673  * activity
9674  */
9675  if( minisrelax || maxisrelax )
9676  continue;
9677 
9678  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9679  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9680 
9681  /* check resactivities for reliability */
9682  if( removescons )
9683  {
9684  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9685  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9686 
9687  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9688  && SCIPisFeasLE(scip, newlhs, minresactivity))
9689  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9690 
9691  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9692  }
9693 
9694  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9695  if( conshdlrdata->multaggrremove && !removescons )
9696  continue;
9697 
9698  /* prefer variables that make the constraints redundant */
9699  if( bestremovescons && !removescons )
9700  continue;
9701 
9702  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9703  * other constraints
9704  */
9705  if( !removescons && nlocks > maxnlocksstay )
9706  continue;
9707 
9708  better = better || (!bestremovescons && removescons);
9709  if( better )
9710  {
9711  bestslackpos = v;
9712  bestslacktype = slacktype;
9713  bestnlocks = nlocks;
9714  bestslackdomrng = slackdomrng;
9715  bestremovescons = removescons;
9716  }
9717  }
9718  }
9719  }
9720 
9721  /* if all coefficients and variables are integral, the right hand side must also be integral */
9722  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9723  {
9724  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9725  SCIPdebugPrintCons(scip, cons, NULL);
9726  *cutoff = TRUE;
9727  return SCIP_OKAY;
9728  }
9729 
9730  supinf = 0;
9731  infinf = 0;
9732  samevar = FALSE;
9733 
9734  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9735  for( v = 0; v < consdata->nvars; ++v )
9736  {
9737  if( v != bestslackpos )
9738  {
9739  if( SCIPisPositive(scip, consdata->vals[v]) )
9740  {
9741  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9742  {
9743  ++supinf;
9744  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9745  {
9746  ++infinf;
9747  samevar = TRUE;
9748  }
9749  }
9750  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9751  ++infinf;
9752 
9753  }
9754  else if( SCIPisNegative(scip, consdata->vals[v]) )
9755  {
9756  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9757  {
9758  ++supinf;
9759  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9760  {
9761  ++infinf;
9762  samevar = TRUE;
9763  }
9764  }
9765  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9766  ++infinf;
9767  }
9768  }
9769  }
9770  assert(!samevar || (supinf > 0 && infinf > 0));
9771 
9772  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9773  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9774  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9775  {
9776  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9777  return SCIP_OKAY;
9778  }
9779 
9780  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9781  * we cannot aggregate the variable, because the integrality condition would get lost
9782  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9783  * loose the integrality condition for this variable.
9784  */
9785  if( bestslackpos >= 0
9786  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9787  || (coefsintegral && varsintegral && nimplvars == 0)) )
9788  {
9789  SCIP_VAR* slackvar;
9790  SCIP_Real* scalars;
9791  SCIP_Real slackcoef;
9792  SCIP_Real aggrconst;
9793  SCIP_Real newlhs;
9794  SCIP_Real newrhs;
9795  SCIP_Bool aggregated;
9796 
9797  /* we found a slack variable that only occurs in at most one other constraint:
9798  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9799  */
9800  assert(bestslackpos < consdata->nvars);
9801 
9802  /* do not multi aggregate binary variables */
9803  if( SCIPvarIsBinary(vars[bestslackpos]) )
9804  return SCIP_OKAY;
9805 
9806  /* convert equality into inequality by deleting the slack variable:
9807  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9808  */
9809  slackvar = vars[bestslackpos];
9810  slackcoef = vals[bestslackpos];
9811  assert(!SCIPisZero(scip, slackcoef));
9812  aggrconst = consdata->rhs/slackcoef;
9813 
9814  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9815  assert(SCIPisLE(scip, newlhs, newrhs));
9816  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9817  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9818  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9819 
9820  /* allocate temporary memory */
9821  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9822 
9823  /* set up the multi-aggregation */
9824  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9825  for( v = 0; v < consdata->nvars; ++v )
9826  {
9827  scalars[v] = -consdata->vals[v]/slackcoef;
9828  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9829  }
9830  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9831  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9832  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9833 
9834  /* perform the multi-aggregation */
9835  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9836  &infeasible, &aggregated) );
9837  assert(aggregated);
9838 
9839  /* free temporary memory */
9840  SCIPfreeBufferArray(scip, &scalars);
9841 
9842  /* check for infeasible aggregation */
9843  if( infeasible )
9844  {
9845  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9846  *cutoff = TRUE;
9847  return SCIP_OKAY;
9848  }
9849 
9850  (*naggrvars)++;
9851 
9852  /* delete the constraint if it became redundant */
9853  if( bestremovescons )
9854  {
9855  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9856  SCIP_CALL( SCIPdelCons(scip, cons) );
9857 
9858  if( !consdata->upgraded )
9859  (*ndelconss)++;
9860  }
9861  }
9862  else if( ncontvars == 1 )
9863  {
9864  SCIP_VAR* var;
9865 
9866  assert(0 <= contvarpos && contvarpos < consdata->nvars);
9867  var = vars[contvarpos];
9868  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
9869 
9870  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9871  {
9872  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
9873  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9874  {
9875  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9876  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
9877  SCIPconsGetName(cons), SCIPvarGetName(var));
9878  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9879  if( infeasible )
9880  {
9881  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9882  *cutoff = TRUE;
9883 
9884  return SCIP_OKAY;
9885  }
9886  }
9887  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
9888  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9889  else if( !SCIPdoNotAggr(scip) )
9890  {
9891  SCIP_VAR* newvar;
9892  SCIP_Real absval;
9893  char newvarname[SCIP_MAXSTRLEN];
9894  SCIP_Bool redundant;
9895  SCIP_Bool aggregated;
9896 
9897  absval = REALABS(vals[contvarpos]);
9898 
9899  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
9900 
9901  /* create new implicit variable for aggregation */
9902  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
9903  SCIP_VARTYPE_IMPLINT, SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) );
9904 
9905  /* add new variable to problem */
9906  SCIP_CALL( SCIPaddVar(scip, newvar) );
9907 
9908 #ifdef WITH_DEBUG_SOLUTION
9909  if( SCIPdebugIsMainscip(scip) )
9910  {
9911  SCIP_Real varval;
9912  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
9913  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
9914  }
9915 #endif
9916 
9917  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9918  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
9919  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
9920 
9921  /* aggregate continuous and implicit variable */
9922  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
9923 
9924  if( infeasible )
9925  {
9926  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
9927  SCIPvarGetName(var), SCIPvarGetName(newvar));
9928  *cutoff = TRUE;
9929 
9930  /* release implicit variable */
9931  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9932 
9933  return SCIP_OKAY;
9934  }
9935 
9936  /* release implicit variable */
9937  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9938 
9939  if( aggregated )
9940  (*naggrvars)++;
9941  else
9942  return SCIP_OKAY;
9943  }
9944 
9945  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
9946  * again
9947  */
9948  consdata->boundstightened = 0;
9949  consdata->rangedrowpropagated = 0;
9950  consdata->presolved = FALSE;
9951  }
9952  }
9953  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
9954  {
9955  SCIP_VAR* var;
9956 
9957  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
9958  * -> we don't convert integers into implints if the row is a 0/1-row
9959  */
9960  assert(varsintegral);
9961  assert(0 <= intvarpos && intvarpos < consdata->nvars);
9962  var = vars[intvarpos];
9963  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
9964 
9965  if( coefsintegral
9966  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
9967  && SCIPisFeasIntegral(scip, consdata->rhs) )
9968  {
9969  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
9970  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
9971  SCIPconsGetName(cons), SCIPvarGetName(var));
9972  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9973  if( infeasible )
9974  {
9975  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9976  *cutoff = TRUE;
9977 
9978  return SCIP_OKAY;
9979  }
9980  }
9981  }
9982 
9983  return SCIP_OKAY;
9984 }
9985 
9986 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
9987 static
9989  SCIP* scip, /**< SCIP data structure */
9990  SCIP_CONSDATA* consdata, /**< linear constraint data */
9991  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
9992  * objective function */
9993  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
9994  * this constraint */
9995  )
9996 {
9997  SCIP_VAR** vars;
9998  SCIP_VAR* var;
9999  SCIP_Real objval;
10000  SCIP_Bool negated;
10001  int nvars;
10002  int v;
10003 
10004  vars = consdata->vars;
10005  nvars = consdata->nvars;
10006 
10007  assert(vars != NULL);
10008 
10009  for( v = 0; v < nvars; ++v )
10010  {
10011  negated = FALSE;
10012  var = vars[v];
10013  assert(var != NULL);
10014 
10015  if( SCIPvarIsNegated(var) )
10016  {
10017  negated = TRUE;
10018  var = SCIPvarGetNegatedVar(var);
10019  assert(var != NULL);
10020  }
10021 
10022  objval = SCIPvarGetObj(var);
10023 
10024  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10025  * function
10026  */
10027  if( SCIPisZero(scip, objval) )
10028  return FALSE;
10029  else
10030  {
10031  SCIP_Real val;
10032 
10033  val = consdata->vals[v];
10034 
10035  if( negated )
10036  {
10037  if( v == 0 )
10038  {
10039  /* the first variable defines the scale */
10040  (*scale) = val / -objval;
10041 
10042  (*offset) += val;
10043  }
10044  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10045  (*offset) += val;
10046  else
10047  return FALSE;
10048  }
10049  else if( v == 0 )
10050  {
10051  /* the first variable defines the scale */
10052  (*scale) = val / objval;
10053  }
10054  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10055  return FALSE;
10056  }
10057  }
10058 
10059  return TRUE;
10060 }
10061 
10062 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10063  * objective coefficients and add an objective offset
10064  */
10065 static
10067  SCIP* scip, /**< SCIP data structure */
10068  SCIP_CONS* cons, /**< linear equation constraint */
10069  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10070  )
10071 {
10072  SCIP_CONSDATA* consdata;
10073  SCIP_Real offset;
10074  SCIP_Real scale;
10075  SCIP_Bool applicable;
10076  int nobjvars;
10077  int nvars;
10078  int v;
10079 
10080  assert(scip != NULL);
10081  assert(cons != NULL);
10082  assert(conshdlrdata != NULL);
10084  consdata = SCIPconsGetData(cons);
10085  assert(consdata != NULL);
10086  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10087 
10088  nvars = consdata->nvars;
10089  nobjvars = SCIPgetNObjVars(scip);
10090 
10091  /* check if the linear equality constraints does not have more variables than the objective function */
10092  if( nvars > nobjvars || nvars == 0 )
10093  return SCIP_OKAY;
10094 
10095  /* check for allowance of algorithm */
10096  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10097  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10098  return SCIP_OKAY;
10099 
10100  offset = consdata->rhs;
10101  scale = 1.0;
10102 
10103  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10104  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10105 
10106  if( applicable )
10107  {
10108  SCIP_VAR** vars;
10109 
10110  vars = consdata->vars;
10111  assert(vars != NULL);
10112 
10113  offset /= scale;
10114 
10115  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10116  SCIPconsGetName(cons), consdata->rhs, offset);
10117 
10118  /* set all objective coefficient to zero */
10119  for( v = 0; v < nvars; ++v )
10120  {
10121  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10122  }
10123 
10124  /* add an objective offset */
10125  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10126  }
10127 
10128  return SCIP_OKAY;
10129 }
10130 
10131 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10132 static
10134  SCIP* scip, /**< SCIP data structure */
10135  SCIP_CONS* cons, /**< constraint */
10136  SCIP_Real primalbound /**< feasible primal bound */
10137  )
10138 {
10139  SCIP_Real cutoffbound;
10140 
10141  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10142  * accepted
10143  */
10144  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10145 
10146  if( cutoffbound < SCIPgetCutoffbound(scip) )
10147  {
10148  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10149 
10150  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10151  }
10152  else
10153  {
10154  SCIP_CONSDATA* consdata;
10155 
10156  consdata = SCIPconsGetData(cons);
10157  assert(consdata != NULL);
10158 
10159  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10160  * resulted from one side
10161  */
10162  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10163  {
10164  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10165  * propagation
10166  */
10167  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10168  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10169  }
10170  }
10171 
10172  return SCIP_OKAY;
10173 }
10174 
10175 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10176  * constraint enters the LP by setting the initial and separated flag to FALSE
10177  */
10178 static
10180  SCIP* scip, /**< SCIP data structure */
10181  SCIP_CONS* cons, /**< linear constraint */
10182  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10183  )
10184 {
10185  SCIP_CONSDATA* consdata;
10186  SCIP_Real offset;
10187  SCIP_Real scale;
10188  SCIP_Bool applicable;
10189  int nobjvars;
10190  int nvars;
10191 
10192  assert(scip != NULL);
10193  assert(cons != NULL);
10194  assert(conshdlrdata != NULL);
10195 
10196  consdata = SCIPconsGetData(cons);
10197  assert(consdata != NULL);
10198 
10199  /* ignore equalities since these are covered by the method checkPartialObjective() */
10200  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10201  return SCIP_OKAY;
10202 
10203  nvars = consdata->nvars;
10204  nobjvars = SCIPgetNObjVars(scip);
10205 
10206  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10207  * initial and/or separated flag is set to FALSE
10208  */
10209  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10210  return SCIP_OKAY;
10211 
10212  offset = 0.0;
10213  scale = 1.0;
10214 
10215  /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10216  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10217  */
10218  if( nobjvars == 0 )
10219  return SCIP_OKAY;
10220 
10221  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10222  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10223 
10224  if( applicable )
10225  {
10226  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10227  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10228 
10229  if( SCIPisPositive(scip, scale) )
10230  {
10231  if( conshdlrdata->detectcutoffbound && rhsfinite )
10232  {
10233  SCIP_Real primalbound;
10234 
10235  primalbound = (consdata->rhs - offset) / scale;
10236 
10237  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10238  SCIPconsGetName(cons), primalbound);
10239 
10240  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10241  }
10242 
10243  if( conshdlrdata->detectlowerbound && lhsfinite )
10244  {
10245  SCIP_Real lowerbound;
10246 
10247  lowerbound = (consdata->lhs - offset) / scale;
10248 
10249  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10250  SCIPconsGetName(cons), lowerbound);
10251 
10252  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10253  }
10254 
10255  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10256  (conshdlrdata->detectlowerbound && !rhsfinite) )
10257  {
10258  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10259  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10260  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10261  }
10262  }
10263  else
10264  {
10265  if( conshdlrdata->detectlowerbound && rhsfinite )
10266  {
10267  SCIP_Real lowerbound;
10268 
10269  lowerbound = (consdata->rhs - offset) / scale;
10270 
10271  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10272  SCIPconsGetName(cons), lowerbound);
10273 
10274  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10275  }
10276 
10277  if( conshdlrdata->detectcutoffbound && lhsfinite )
10278  {
10279  SCIP_Real primalbound;
10280 
10281  primalbound = (consdata->lhs - offset) / scale;
10282 
10283  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10284  SCIPconsGetName(cons), primalbound);
10285 
10286  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10287  }
10288 
10289  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10290  (conshdlrdata->detectlowerbound && !lhsfinite) )
10291  {
10292  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10293  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10294  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10295  }
10296  }
10297  }
10298 
10299  return SCIP_OKAY;
10300 }
10301 
10302 /** converts special equalities */
10303 static
10305  SCIP* scip, /**< SCIP data structure */
10306  SCIP_CONS* cons, /**< linear constraint */
10307  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10308  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10309  int* nfixedvars, /**< pointer to count number of fixed variables */
10310  int* naggrvars, /**< pointer to count number of aggregated variables */
10311  int* ndelconss /**< pointer to count number of deleted constraints */
10312  )
10313 {
10314  SCIP_CONSDATA* consdata;
10315 
10316  assert(scip != NULL);
10317  assert(cons != NULL);
10318  assert(conshdlrdata != NULL);
10319  assert(cutoff != NULL);
10320  assert(nfixedvars != NULL);
10321  assert(naggrvars != NULL);
10322  assert(ndelconss != NULL);
10323 
10324  consdata = SCIPconsGetData(cons);
10325  assert(consdata != NULL);
10326  assert(consdata->removedfixings);
10327 
10328  /* do nothing on inequalities */
10329  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10330  return SCIP_OKAY;
10331 
10332  /* depending on the number of variables, call a special conversion method */
10333  if( consdata->nvars == 1 )
10334  {
10335  /* fix variable */
10336  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10337  }
10338  else if( consdata->nvars == 2 )
10339  {
10340  /* aggregate one of the variables */
10341  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10342  }
10343  else
10344  {
10345  /* check if the equality is part of the objective function */
10346  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10347 
10348  /* try to multi-aggregate one of the variables */
10349  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10350  }
10351 
10352  return SCIP_OKAY;
10353 }
10354 
10355 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10356  * integral
10357  */
10358 static
10360  SCIP* scip, /**< SCIP data structure */
10361  SCIP_CONSDATA* consdata, /**< linear constraint */
10362  int pos, /**< position of variable to be left out */
10363  SCIP_Real val /**< value to divide the coefficients by */
10364  )
10365 {
10366  int v;
10367 
10368  assert(scip != NULL);
10369  assert(consdata != NULL);
10370  assert(0 <= pos && pos < consdata->nvars);
10371 
10372  for( v = 0; v < consdata->nvars; ++v )
10373  {
10374  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10375  return FALSE;
10376  }
10377 
10378  return TRUE;
10379 }
10380 
10381 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10382  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10383  */
10384 static
10386  SCIP* scip, /**< SCIP data structure */
10387  SCIP_Real side, /**< lhs or rhs */
10388  SCIP_Real val, /**< coefficient */
10389  SCIP_Real minresactivity, /**< minimal residual activity */
10390  SCIP_Real maxresactivity, /**< maximal residual activity */
10391  SCIP_Real* minval, /**< pointer to store calculated minval */
10392  SCIP_Real* maxval /**< pointer to store calculated maxval */
10393  )
10394 {
10395  assert(scip != NULL);
10396  assert(minval != NULL);
10397  assert(maxval != NULL);
10398 
10399  if( val > 0.0 )
10400  {
10401  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10402  *minval = -maxresactivity;
10403  else
10404  *minval = (side - maxresactivity)/val;
10405 
10406  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10407  *maxval = -minresactivity;
10408  else
10409  *maxval = (side - minresactivity)/val;
10410  }
10411  else
10412  {
10413  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10414  *minval = minresactivity;
10415  else
10416  *minval = (side - minresactivity)/val;
10417 
10418  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10419  *maxval = maxresactivity;
10420  else
10421  *maxval = (side - maxresactivity)/val;
10422  }
10423 }
10424 
10425 
10426 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10427  * linear inequality
10428  */
10429 static
10431  SCIP* scip, /**< SCIP data structure */
10432  SCIP_CONS* cons, /**< linear constraint */
10433  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10434  int* nfixedvars, /**< pointer to count number of fixed variables */
10435  int* naggrvars, /**< pointer to count number of aggregated variables */
10436  int* ndelconss /**< pointer to count number of deleted constraints */
10437  )
10438 {
10439  SCIP_CONSDATA* consdata;
10440  SCIP_Bool lhsexists;
10441  SCIP_Bool rhsexists;
10442  SCIP_Bool bestisint;
10443  SCIP_Bool bestislhs;
10444  int bestpos;
10445  int i;
10446  int maxotherlocks;
10448  assert(scip != NULL);
10449  assert(cons != NULL);
10450  assert(cutoff != NULL);
10451  assert(nfixedvars != NULL);
10452  assert(naggrvars != NULL);
10453  assert(ndelconss != NULL);
10454 
10455  /* only process checked constraints (for which the locks are increased);
10456  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10457  * dualfix presolver
10458  */
10459  if( !SCIPconsIsChecked(cons) )
10460  return SCIP_OKAY;
10461 
10462  consdata = SCIPconsGetData(cons);
10463  assert(consdata != NULL);
10464 
10465  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10466  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10467 
10468  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10469  * can use it safely for aggregation and break the search loop
10470  */
10471  bestpos = -1;
10472  bestisint = TRUE;
10473  bestislhs = FALSE;
10474 
10475  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10476  * everything else would produce fill-in. Exceptions:
10477  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10478  * produced.
10479  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10480  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10481  * six nonzeros (two variables per substitution).
10482  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10483  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10484  * six nonzeros (three variables per substitution). God exists!
10485  */
10486  if( consdata->nvars <= 2 )
10487  maxotherlocks = INT_MAX;
10488  else if( consdata->nvars == 3 )
10489  maxotherlocks = 3;
10490  else if( consdata->nvars == 4 )
10491  maxotherlocks = 2;
10492  else
10493  maxotherlocks = 1;
10494 
10495  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10496  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10497  maxotherlocks++;
10498 
10499  for( i = 0; i < consdata->nvars && bestisint; ++i )
10500  {
10501  SCIP_VAR* var;
10502  SCIP_Bool isint;
10503  SCIP_Real val;
10504  SCIP_Real obj;
10505  SCIP_Real lb;
10506  SCIP_Real ub;
10507  SCIP_Bool agglhs;
10508  SCIP_Bool aggrhs;
10509 
10510  var = consdata->vars[i];
10512 
10513  /* if we already found a candidate, skip integers */
10514  if( bestpos >= 0 && isint )
10515  continue;
10516 
10517  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10518  * active, fixed, or single-aggregated with another binary variable
10519  */
10520  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10521  continue;
10522 
10523  if ( SCIPdoNotMultaggrVar(scip, var) )
10524  continue;
10525 
10526  val = consdata->vals[i];
10527  obj = SCIPvarGetObj(var);
10528  lb = SCIPvarGetLbGlobal(var);
10529  ub = SCIPvarGetUbGlobal(var);
10530 
10531  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10532  *
10533  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10534  * - constraint is the only one that forbids fixing the variable to its lower bound
10535  * - 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
10536  *
10537  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10538  * - constraint is the only one that forbids fixing the variable to its upper bound
10539  * - 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
10540  *
10541  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10542  * - constraint is the only one that forbids fixing the variable to its upper bound
10543  * - 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
10544  *
10545  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10546  * - constraint is the only one that forbids fixing the variable to its lower bound
10547  * - 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
10548  *
10549  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10550  * of all x_j
10551  * furthermore: we only want to apply this, if no fill-in will be produced
10552  */
10553  agglhs = lhsexists
10554  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10555  && SCIPvarGetNLocksUp(var) <= maxotherlocks)
10556  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10557  && SCIPvarGetNLocksDown(var) <= maxotherlocks));
10558  aggrhs = rhsexists
10559  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10560  && SCIPvarGetNLocksDown(var) <= maxotherlocks)
10561  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10562  && SCIPvarGetNLocksUp(var) <= maxotherlocks));
10563  if( agglhs || aggrhs )
10564  {
10565  SCIP_Real minresactivity;
10566  SCIP_Real maxresactivity;
10567  SCIP_Real minval;
10568  SCIP_Real maxval;
10569  SCIP_Bool minisrelax;
10570  SCIP_Bool maxisrelax;
10571  SCIP_Bool isminsettoinfinity;
10572  SCIP_Bool ismaxsettoinfinity;
10573 
10574  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10575  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10576  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10577  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10578 
10579  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10580  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10581  * This is needed, because we do not want to rely on relaxed finite resactivities.
10582  */
10583  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10584 
10585  if( agglhs )
10586  {
10587  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10588  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10589 
10590  assert(SCIPisLE(scip, minval, maxval));
10591  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10592  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10593  {
10594  SCIP_Real oldmaxresactivity;
10595  SCIP_Real oldminresactivity;
10596  SCIP_Bool recalculated;
10597 
10598  recalculated = FALSE;
10599  oldmaxresactivity = maxresactivity;
10600  oldminresactivity = minresactivity;
10601 
10602  /* check minresactivity for reliability */
10603  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10604  {
10605  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10606  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10607  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10608  }
10609 
10610  /* check maxresactivity for reliability */
10611  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10612  {
10613  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10614  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10615  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10616  }
10617 
10618  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10619  if( recalculated )
10620  {
10621  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10622 
10623  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10624  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10625 
10626  assert(SCIPisLE(scip, minval, maxval));
10627  }
10628 
10629  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10630  {
10631  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10632  * in the multi-aggregation
10633  */
10634  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10635  {
10636  bestpos = i;
10637  bestisint = isint;
10638  bestislhs = TRUE;
10639  continue; /* no need to also look at the right hand side */
10640  }
10641  }
10642  }
10643  }
10644 
10645  if( aggrhs )
10646  {
10647  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10648  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10649 
10650  assert(SCIPisLE(scip,minval,maxval));
10651  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10652  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10653  {
10654  SCIP_Real oldmaxresactivity;
10655  SCIP_Real oldminresactivity;
10656  SCIP_Bool recalculated;
10657 
10658  recalculated = FALSE;
10659  oldmaxresactivity = maxresactivity;
10660  oldminresactivity = minresactivity;
10661 
10662  /* check minresactivity for reliability */
10663  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10664  {
10665  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10666  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10667  }
10668 
10669  /* check maxresactivity for reliability */
10670  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10671  {
10672  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10673  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10674  }
10675 
10676  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10677  if( recalculated )
10678  {
10679  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10680  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10681  assert(SCIPisLE(scip,minval,maxval));
10682  }
10683 
10684  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10685  {
10686  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10687  * in the multi-aggregation
10688  */
10689  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10690  {
10691  bestpos = i;
10692  bestisint = isint;
10693  bestislhs = FALSE;
10694  }
10695  }
10696  }
10697  }
10698  }
10699  }
10700 
10701  if( bestpos >= 0 )
10702  {
10703  SCIP_VAR** aggrvars;
10704  SCIP_Real* aggrcoefs;
10705  SCIP_Real aggrconst;
10706  SCIP_VAR* bestvar;
10707  SCIP_Real bestval;
10708  SCIP_Real epsilon;
10709  int naggrs;
10710  int j;
10711  SCIP_Bool infeasible;
10712  SCIP_Bool aggregated;
10713  SCIP_Bool samevar;
10714  int supinf; /* counter for infinite contributions to the supremum of a possible
10715  * multi-aggregation
10716  */
10717  int infinf; /* counter for infinite contributions to the infimum of a possible
10718  * multi-aggregation
10719  */
10720 
10721  assert(!bestislhs || lhsexists);
10722  assert(bestislhs || rhsexists);
10723 
10724  bestvar = consdata->vars[bestpos];
10725  bestval = consdata->vals[bestpos];
10726  assert(bestisint ==
10728 
10729  /* allocate temporary memory */
10730  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10731  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10732 
10733  /* set up the multi-aggregation */
10734  SCIPdebugPrintCons(scip, cons, NULL);
10735  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10736  naggrs = 0;
10737  supinf = 0;
10738  infinf = 0;
10739  samevar = FALSE;
10740  epsilon = SCIPepsilon(scip);
10741 
10742  for( j = 0; j < consdata->nvars; ++j )
10743  {
10744  if( j != bestpos )
10745  {
10746  SCIP_Real absaggrcoef;
10747 
10748  aggrvars[naggrs] = consdata->vars[j];
10749  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10750  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10751 
10752  absaggrcoef = REALABS(aggrcoefs[naggrs]);
10753 
10754  /* do not try to multi aggregate, when numerical bad */
10755  if( absaggrcoef < epsilon )
10756  {
10757  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10758 
10759  /* free temporary memory */
10760  SCIPfreeBufferArray(scip, &aggrcoefs);
10761  SCIPfreeBufferArray(scip, &aggrvars);
10762 
10763  return SCIP_OKAY;
10764  }
10765 
10766  if( bestisint )
10767  {
10768  /* coefficient must be integral: round it to exact integral value */
10769  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10770  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10771  }
10772 
10773  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10774  {
10775  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10776  {
10777  ++supinf;
10778  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10779  {
10780  ++infinf;
10781  samevar = TRUE;
10782  }
10783  }
10784  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10785  ++infinf;
10786  }
10787  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10788  {
10789  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10790  {
10791  ++supinf;
10792  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10793  {
10794  ++infinf;
10795  samevar = TRUE;
10796  }
10797  }
10798  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10799  ++infinf;
10800  }
10801 
10802  naggrs++;
10803  }
10804  }
10805  assert(!samevar || (supinf > 0 && infinf > 0));
10806 
10807  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10808  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10809  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10810  assert(naggrs == consdata->nvars-1);
10811 
10812  /* right hand side must be integral: round it to exact integral value */
10813  if( bestisint )
10814  {
10815  assert(SCIPisIntegral(scip, aggrconst));
10816  aggrconst = SCIPfloor(scip, aggrconst+0.5);
10817  }
10818 
10819  aggregated = FALSE;
10820  infeasible = FALSE;
10821 
10822  /* perform the multi-aggregation */
10823  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
10824  {
10825  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
10826  * also convertLongEquality() early termination due to coefficients
10827  */
10828  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10829  }
10830  else
10831  {
10832  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10833  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10834  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10835  }
10836  /* free temporary memory */
10837  SCIPfreeBufferArray(scip, &aggrcoefs);
10838  SCIPfreeBufferArray(scip, &aggrvars);
10839 
10840  /* check for infeasible aggregation */
10841  if( infeasible )
10842  {
10843  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10844  *cutoff = TRUE;
10845  return SCIP_OKAY;
10846  }
10847 
10848  /* delete the constraint, if the aggregation was successful */
10849  if( aggregated )
10850  {
10851  SCIP_CALL( SCIPdelCons(scip, cons) );
10852 
10853  if( !consdata->upgraded )
10854  (*ndelconss)++;
10855  (*naggrvars)++;
10856  }
10857  else
10858  {
10859  SCIPdebugMsg(scip, "aggregation non successful!\n");
10860  }
10861  }
10862 
10863  return SCIP_OKAY;
10864 }
10865 
10866 #define BINWEIGHT 1
10867 #define INTWEIGHT 4
10868 #define CONTWEIGHT 8
10869 
10870 /** gets weight for variable in a "weighted number of variables" sum */
10871 static
10872 int getVarWeight(
10873  SCIP_VAR* var /**< variable to get weight for */
10874  )
10875 {
10876  switch( SCIPvarGetType(var) )
10877  {
10878  case SCIP_VARTYPE_BINARY:
10879  return BINWEIGHT;
10880  case SCIP_VARTYPE_INTEGER:
10881  case SCIP_VARTYPE_IMPLINT:
10882  return INTWEIGHT;
10884  return CONTWEIGHT;
10885  default:
10886  SCIPerrorMessage("invalid variable type\n");
10887  SCIPABORT();
10888  return 0; /*lint !e527*/
10889  }
10890 }
10891 
10892 /** tries to aggregate variables in equations a^Tx = lhs
10893  * in case there are at most two binary variables with an odd coefficient and all other
10894  * variables are not continuous and have an even coefficient then:
10895  * - exactly one odd binary variables
10896  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
10897  * - lhs is odd -> y = 1
10898  * - lhs is even -> y = 0
10899  * - exactly two odd binary variables
10900  * aggregate the two binary variables with odd coefficient
10901  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
10902  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
10903  */
10904 static
10906  SCIP* scip, /**< SCIP data structure */
10907  SCIP_CONS* cons, /**< linear constraint */
10908  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10909  int* nfixedvars, /**< pointer to count number of fixed variables */
10910  int* naggrvars, /**< pointer to count number of aggregated variables */
10911  int* ndelconss /**< pointer to count number of deleted constraints */
10912  )
10913 { /*lint --e{715}*/
10914  SCIP_CONSDATA* consdata;
10915  SCIP_Bool success;
10916 
10917  assert( scip != NULL );
10918  assert( cons != NULL );
10919 
10920  consdata = SCIPconsGetData(cons);
10921  assert( consdata != NULL );
10923  /* check if the linear constraint is an equation with integral right hand side */
10924  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
10925  return SCIP_OKAY;
10926 
10927  /* try to fix and aggregated variables until nothing is possible anymore */
10928  do
10929  {
10930  int v;
10931  int nvars;
10932  SCIP_VAR** vars;
10933  SCIP_Real* vals;
10934  SCIP_Real lhs;
10935  SCIP_Bool lhsodd;
10936 
10937  SCIP_Bool infeasible;
10938  SCIP_Bool fixed;
10939  SCIP_Bool aggregated;
10940  SCIP_Bool redundant;
10941 
10942  SCIP_VAR* var1;
10943  SCIP_VAR* var2;
10944  int noddvars;
10945 
10946  success = FALSE;
10947 
10948  lhs = consdata->lhs;
10949  vars = consdata->vars;
10950  vals = consdata->vals;
10951  nvars = consdata->nvars;
10952 
10953  assert( !SCIPisInfinity(scip, ABS(lhs)) );
10954 
10955  var1 = NULL;
10956  var2 = NULL;
10957  noddvars = 0;
10958 
10959  /* search for binary variables with an odd coefficient */
10960  for( v = 0; v < nvars && noddvars < 3; ++v )
10961  {
10962  SCIP_Longint val;
10963 
10964  /* all coefficients and variables have to be integral */
10965  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10966  return SCIP_OKAY;
10967 
10968  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
10969  if( val % 2 != 0 )
10970  {
10971  /* the odd values have to belong to binary variables */
10972  if( !SCIPvarIsBinary(vars[v]) )
10973  return SCIP_OKAY;
10974 
10975  if( noddvars == 0 )
10976  var1 = vars[v];
10977  else
10978  var2 = vars[v];
10979 
10980  noddvars++;
10981  }
10982  }
10983 
10984  /* check lhs is odd or even */
10985  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
10986 
10987  if( noddvars == 1 )
10988  {
10989  assert( var1 != NULL );
10990 
10991  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
10992  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
10993 
10994  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
10995 
10996  /* check for infeasibility of fixing */
10997  if( infeasible )
10998  {
10999  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11000  *cutoff = TRUE;
11001  return SCIP_OKAY;
11002  }
11003 
11004  if( fixed )
11005  {
11006  SCIPdebugMsg(scip, " -> feasible fixing\n");
11007  (*nfixedvars)++;
11008  success = TRUE;
11009  }
11010  }
11011  else if( noddvars == 2 )
11012  {
11013  assert( var1 != NULL );
11014  assert( var2 != NULL );
11015 
11016  /* aggregate the two variables with odd coefficient
11017  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11018  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11019  */
11020  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11021  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11022 
11023  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11024  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11025 
11026  /* check for infeasibility of aggregation */
11027  if( infeasible )
11028  {
11029  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11030  *cutoff = TRUE;
11031  return SCIP_OKAY;
11032  }
11033 
11034  /* count the aggregation */
11035  if( aggregated )
11036  {
11037  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11038  (*naggrvars)++;
11039  success = TRUE;
11040  }
11041  }
11042 
11043  if( success )
11044  {
11045  /* apply fixings and aggregation to successfully rerun this presolving step */
11046  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11047 
11048  if( infeasible )
11049  {
11050  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11051  *cutoff = TRUE;
11052  return SCIP_OKAY;
11053  }
11054 
11055  /* normalize constraint */
11056  SCIP_CALL( normalizeCons(scip, cons) );
11057  }
11058  }
11059  while( success );
11060 
11061  return SCIP_OKAY;
11062 }
11063 
11064 
11065 
11066 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11067  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11068  * coefficients
11069  */
11070 static
11071 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11072 { /*lint --e{715}*/
11073  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11074  SCIP_VARTYPE vartype1;
11075  SCIP_VARTYPE vartype2;
11076  SCIP_Real value;
11077 
11078  assert(consdata != NULL);
11079  assert(0 <= ind1 && ind1 < consdata->nvars);
11080  assert(0 <= ind2 && ind2 < consdata->nvars);
11081 
11082  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11083  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11084 
11085  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11086  {
11087  /* continuous varibles will be sorted to the back */
11088  if( vartype2 != vartype1 )
11089  return +1;
11090  /* both variables are continuous */
11091  else
11092  return 0;
11093  }
11094  /* continuous variables will be sorted to the back */
11095  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11096  return -1;
11097 
11098  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11099 
11100  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11101  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11102 }
11103 
11104 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11105  * common divisor
11106  *
11107  * 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
11108  * constraint to 1^Tx = 1
11109  */
11110 static
11112  SCIP* scip, /**< SCIP data structure */
11113  SCIP_CONS* cons, /**< linear constraint */
11114  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11115  int* nchgsides /**< pointer to store the amount of changed sides */
11116  )
11117 {
11118  SCIP_CONSDATA* consdata;
11119  SCIP_VAR** vars;
11120  SCIP_Real* vals;
11121  SCIP_Real minval;
11122  SCIP_Real secondminval;
11123  SCIP_Real maxval;
11124  SCIP_Real lhs;
11125  SCIP_Real rhs;
11126  int nvars;
11127  int v;
11129  /* we must not change a modifiable constraint in any way */
11130  if( SCIPconsIsModifiable(cons) )
11131  return SCIP_OKAY;
11132 
11133  if( SCIPconsIsDeleted(cons) )
11134  return SCIP_OKAY;
11135 
11136  consdata = SCIPconsGetData(cons);
11137  assert(consdata != NULL);
11138 
11139  nvars = consdata->nvars;
11140 
11141  /* do not check empty or bound-constraints */
11142  if( nvars < 2 )
11143  return SCIP_OKAY;
11144 
11145  vals = consdata->vals;
11146  vars = consdata->vars;
11147  assert(vars != NULL);
11148  assert(vals != NULL);
11149 
11150  lhs = consdata->lhs;
11151  rhs = consdata->rhs;
11152  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11153  assert(!SCIPisNegative(scip, rhs));
11154 
11155  minval = SCIP_INVALID;
11156  secondminval = SCIP_INVALID;
11157  maxval = -SCIP_INVALID;
11158 
11159  for( v = nvars - 1; v >= 0; --v )
11160  {
11161  if( SCIPvarIsBinary(vars[v]) )
11162  {
11163  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11164  {
11165  secondminval = minval;
11166  minval = vals[v];
11167  }
11168  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11169  secondminval = vals[v];
11170 
11171  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11172  maxval = vals[v];
11173  }
11174  else
11175  break;
11176  }
11177 
11178  /* check if all variables are binary */
11179  if( v == -1 )
11180  {
11181  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11182  return SCIP_OKAY;
11183 
11184  /* check if we can and need to choose exactly one binary variable */
11185  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11186  {
11187  /* change all coefficients to 1.0 */
11188  for( v = nvars - 1; v >= 0; --v )
11189  {
11190  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11191  }
11192  (*nchgcoefs) += nvars;
11193 
11194  /* replace old right and left hand side with 1.0 */
11195  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11196  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11197  (*nchgsides) += 2;
11198  }
11199  }
11200 
11201  return SCIP_OKAY;
11202 }
11203 
11204 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11205  * for equations @see rangedRowSimplify() will be called
11206  *
11207  * there are several different coefficient reduction steps which will be applied
11208  *
11209  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11210  *
11211  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11212  *
11213  * 2. We try to remove redundant fractional parts in a constraint
11214  *
11215  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11216  *
11217  * 3. We are using the greatest common divisor for further reductions
11218  *
11219  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11220  * integral
11221  */
11222 static
11224  SCIP* scip, /**< SCIP data structure */
11225  SCIP_CONS* cons, /**< linear constraint */
11226  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11227  int* nchgsides /**< pointer to store the amount of changed sides */
11228  )
11229 {
11230  SCIP_CONSDATA* consdata;
11231  SCIP_VAR** vars;
11232  SCIP_Real* vals;
11233  int* perm;
11234  SCIP_Real minactsub;
11235  SCIP_Real maxactsub;
11236  SCIP_Real siderest;
11237  SCIP_Real feastol;
11238  SCIP_Real newcoef;
11239  SCIP_Real absval;
11241  SCIP_Real lhs;
11242  SCIP_Real rhs;
11243  SCIP_Real lb;
11244  SCIP_Real ub;
11245  SCIP_Longint restcoef;
11246  SCIP_Longint oldgcd;
11247  SCIP_Longint rest;
11248  SCIP_Longint gcd;
11249  SCIP_Bool isminsettoinfinity;
11250  SCIP_Bool ismaxsettoinfinity;
11251  SCIP_Bool isminrelax;
11252  SCIP_Bool ismaxrelax;
11253  SCIP_Bool allcoefintegral;
11254  SCIP_Bool onlybin;
11255  SCIP_Bool hasrhs;
11256  SCIP_Bool haslhs;
11257  int oldnchgcoefs;
11258  int oldnchgsides;
11259  int foundbin;
11260  int candpos;
11261  int candpos2;
11262  int offsetv;
11263  int nvars;
11264  int v;
11265  int w;
11266 
11267  assert(scip != NULL);
11268  assert(cons != NULL);
11269  assert(nchgcoefs != NULL);
11270  assert(nchgsides != NULL);
11271 
11272  /* we must not change a modifiable constraint in any way */
11273  if( SCIPconsIsModifiable(cons) )
11274  return SCIP_OKAY;
11275 
11276  if( SCIPconsIsDeleted(cons) )
11277  return SCIP_OKAY;
11278 
11279  consdata = SCIPconsGetData(cons);
11280  assert(consdata != NULL);
11281 
11282  nvars = consdata->nvars;
11283 
11284  /* do not check empty or bound-constraints */
11285  if( nvars <= 2 )
11286  return SCIP_OKAY;
11287 
11288  /* update maximal activity delta if necessary */
11289  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11290  consdataRecomputeMaxActivityDelta(scip, consdata);
11291 
11292  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11293  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11294  checkMaxActivityDelta(scip, consdata);
11295 
11296  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11297  * accordingly
11298  */
11299  /* can only work with valid non-infinity activities per variable */
11300  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11301  return SCIP_OKAY;
11302 
11303  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11304  * but the eventsystem seems to be full
11305  */
11306  consdata->normalized = FALSE;
11307 
11308  /* normalize constraint */
11309  SCIP_CALL( normalizeCons(scip, cons) );
11310  assert(nvars == consdata->nvars);
11311 
11312  if( !consdata->normalized )
11313  return SCIP_OKAY;
11314 
11315  lhs = consdata->lhs;
11316  rhs = consdata->rhs;
11317  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11318  assert(!SCIPisNegative(scip, rhs));
11319 
11320  if( !SCIPisInfinity(scip, -lhs) )
11321  haslhs = TRUE;
11322  else
11323  haslhs = FALSE;
11324 
11325  if( !SCIPisInfinity(scip, rhs) )
11326  hasrhs = TRUE;
11327  else
11328  hasrhs = FALSE;
11329 
11330  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11331  SCIPdebug( oldnchgsides = *nchgsides; )
11332 
11333  /* @todo also work on ranged rows */
11334  if( haslhs && hasrhs )
11335  {
11336  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11337 
11338  return SCIP_OKAY;
11339  }
11340  assert(haslhs != hasrhs);
11341 
11342  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11343  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11344  assert(!haslhs || !SCIPisNegative(scip, lhs));
11345 
11346  /* get temporary memory to store the sorted permutation */
11347  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11348 
11349  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11350  * value of their coefficients
11351  */
11352  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11353 
11354  /* perform sorting after permutation array */
11355  permSortConsdata(consdata, perm, nvars);
11356  consdata->sorted = FALSE;
11357  consdata->binvarssorted = FALSE;
11358 
11359  vars = consdata->vars;
11360  vals = consdata->vals;
11361  assert(vars != NULL);
11362  assert(vals != NULL);
11363  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11364 
11365  /* free temporary memory */
11366  SCIPfreeBufferArray(scip, &perm);
11367 
11368  /* only check constraints with at least two non continuous variables */
11369  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11370  return SCIP_OKAY;
11371 
11372  /* do not process constraints when all coefficients are 1.0 */
11373  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11374  return SCIP_OKAY;
11375 
11376  feastol = SCIPfeastol(scip);
11377 
11378  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11379  SCIPdebugPrintCons(scip, cons, NULL);
11380 
11381  /* get global activities */
11382  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11383  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11384 
11385  /* cannot work with infinite activities */
11386  if( isminsettoinfinity || ismaxsettoinfinity )
11387  return SCIP_OKAY;
11388 
11389  assert(!isminrelax);
11390  assert(!ismaxrelax);
11391  assert(maxactsub > minactsub);
11392  assert(!SCIPisInfinity(scip, -minactsub));
11393  assert(!SCIPisInfinity(scip, maxactsub));
11394 
11395  v = 0;
11396  offsetv = -1;
11397  side = haslhs ? lhs : rhs;
11398 
11399  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11400  * do not need to look at the large coefficients
11401  *
11402  * e.g. all x are binary, z are positive integer
11403  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11404  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11405  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11406  *
11407  * can be changed to
11408  *
11409  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11410  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11411  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11412  */
11413 
11414  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11415  * hand side, we cannot apply the extra reduction step and need to reset v
11416  *
11417  * 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
11418  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11419  * for all i is a solution
11420  *
11421  * also redundancy of variables would not be correctly determined in such a case
11422  */
11423  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11424  {
11425  v = 1;
11426 
11427  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11428  {
11429  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11430  * extra step, which might have worked
11431  */
11432  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11433  {
11434  v = 0;
11435  break;
11436  }
11437 
11438  ++v;
11439  }
11440 
11441  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11442  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11443  if( v == nvars )
11444  return SCIP_OKAY;
11445 
11446  /* cannot work with continuous variables which have a big coefficient */
11447  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11448  return SCIP_OKAY;
11449 
11450  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11451  if( SCIPisEQ(scip, side, -vals[v]) )
11452  v = 0;
11453 
11454  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11455  * reduction
11456  */
11457  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11458  v = 0;
11459 
11460  if( v > 0 )
11461  {
11462  assert(v < nvars);
11463 
11464  offsetv = v - 1;
11465 
11466  for( w = 0; w < v; ++w )
11467  {
11468  lb = SCIPvarGetLbGlobal(vars[w]);
11469  ub = SCIPvarGetUbGlobal(vars[w]);
11470 
11471  assert(vals[w] > 0);
11472 
11473  /* update residual activities */
11474  maxactsub -= ub * vals[w];
11475  minactsub -= lb * vals[w];
11476  assert(maxactsub > minactsub);
11477  }
11478  }
11479  }
11480 
11481  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11482  *
11483  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11484  *
11485  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11486  * to
11487  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11488  */
11489  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11490  {
11491  SCIP_Bool redundant = FALSE;
11492 
11493  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11494  assert(gcd >= 1);
11495 
11496  if( v == 0 )
11497  {
11498  lb = SCIPvarGetLbGlobal(vars[0]);
11499  ub = SCIPvarGetUbGlobal(vars[0]);
11500 
11501  /* update residual activities */
11502  if( vals[0] > 0 )
11503  {
11504  maxactsub -= ub * vals[0];
11505  minactsub -= lb * vals[0];
11506  }
11507  else
11508  {
11509  maxactsub -= lb * vals[0];
11510  minactsub -= ub * vals[0];
11511  }
11512  assert(maxactsub > minactsub);
11513  ++v;
11514  }
11515 
11516  siderest = -SCIP_INVALID;
11517  allcoefintegral = TRUE;
11518 
11519  /* check if some variables always fit into the given constraint */
11520  for( ; v < nvars - 1; ++v )
11521  {
11522  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11523  break;
11524 
11525  if( !SCIPisIntegral(scip, vals[v]) )
11526  {
11527  allcoefintegral = FALSE;
11528  break;
11529  }
11530 
11531  /* calculate greatest common divisor for all general and binary variables */
11532  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11533 
11534  if( gcd == 1 )
11535  break;
11536 
11537  lb = SCIPvarGetLbGlobal(vars[v]);
11538  ub = SCIPvarGetUbGlobal(vars[v]);
11539 
11540  assert(!SCIPisInfinity(scip, -lb));
11541  assert(!SCIPisInfinity(scip, ub));
11542 
11543  /* update residual activities */
11544  if( vals[v] > 0 )
11545  {
11546  maxactsub -= ub * vals[v];
11547  minactsub -= lb * vals[v];
11548  }
11549  else
11550  {
11551  maxactsub -= lb * vals[v];
11552  minactsub -= ub * vals[v];
11553  }
11554  assert(SCIPisGE(scip, maxactsub, minactsub));
11555 
11556  if( hasrhs )
11557  {
11558  /* determine the remainder of the right hand side and the gcd */
11559  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11560  }
11561  else
11562  {
11563  /* determine the remainder of the left hand side and the gcd */
11564  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11565  if( SCIPisZero(scip, siderest) )
11566  siderest = gcd;
11567  }
11568 
11569  /* early termination if the activities deceed the gcd */
11570  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11571  {
11572  redundant = TRUE;
11573  break;
11574  }
11575  }
11576  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11577 
11578  if( !redundant )
11579  {
11580  if( hasrhs )
11581  {
11582  /* determine the remainder of the right hand side and the gcd */
11583  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11584  }
11585  else
11586  {
11587  /* determine the remainder of the left hand side and the gcd */
11588  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11589  if( SCIPisZero(scip, siderest) )
11590  siderest = gcd;
11591  }
11592  }
11593  else
11594  ++v;
11595 
11596  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",
11597  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11598 
11599  /* check if we can remove redundant variables */
11600  if( v < nvars && (redundant ||
11601  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11602  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11603  {
11604  SCIP_Real oldcoef;
11605 
11606  /* double check the redundancy */
11607 #ifndef NDEBUG
11608  SCIP_Real tmpminactsub = 0.0;
11609  SCIP_Real tmpmaxactsub = 0.0;
11610 
11611  /* recompute residual activities */
11612  for( w = v; w < nvars; ++w )
11613  {
11614  lb = SCIPvarGetLbGlobal(vars[w]);
11615  ub = SCIPvarGetUbGlobal(vars[w]);
11616 
11617  assert(!SCIPisInfinity(scip, -lb));
11618  assert(!SCIPisInfinity(scip, ub));
11619 
11620  /* update residual activities */
11621  if( vals[w] > 0 )
11622  {
11623  tmpmaxactsub += ub * vals[w];
11624  tmpminactsub += lb * vals[w];
11625  }
11626  else
11627  {
11628  tmpmaxactsub += lb * vals[w];
11629  tmpminactsub += ub * vals[w];
11630  }
11631  assert(tmpmaxactsub >= tmpminactsub);
11632  }
11633 
11634  if( hasrhs )
11635  {
11636  assert(offsetv == -1);
11637 
11638  /* determine the remainder of the right hand side and the gcd */
11639  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11640  }
11641  else
11642  {
11643  /* determine the remainder of the left hand side and the gcd */
11644  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11645  if( SCIPisZero(scip, siderest) )
11646  siderest = gcd;
11647  }
11648 
11649  /* does the redundancy really is fulfilled */
11650  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11651 #endif
11652 
11653  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11654  nvars - v, SCIPconsGetName(cons));
11655 
11656  /* remove redundant variables */
11657  for( w = nvars - 1; w >= v; --w )
11658  {
11659  SCIP_CALL( delCoefPos(scip, cons, w) );
11660  }
11661  (*nchgcoefs) += (nvars - v);
11662 
11663  assert(w >= 0);
11664 
11665  oldcoef = vals[w];
11666 
11667  /* normalize constraint */
11668  SCIP_CALL( normalizeCons(scip, cons) );
11669  assert(vars == consdata->vars);
11670  assert(vals == consdata->vals);
11671  assert(w < consdata->nvars);
11672 
11673  /* compute new greatest common divisor due to normalization */
11674  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11675  assert(gcd >= 1);
11676 
11677  /* update side */
11678  if( hasrhs )
11679  {
11680  /* replace old with new right hand side */
11681  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11682  rhs = consdata->rhs;
11683  }
11684  else
11685  {
11686  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11687  {
11688  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11689  lhs = consdata->lhs;
11690  }
11691  else
11692  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11693  }
11694  ++(*nchgsides);
11695 
11696  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11697  assert(!haslhs || !SCIPisNegative(scip, lhs));
11698 
11699  /* get new constraint data */
11700  nvars = consdata->nvars;
11701  assert(nvars >= 2);
11702 
11703  allcoefintegral = TRUE;
11704 
11705 #ifndef NDEBUG
11706  /* check integrality */
11707  for( w = offsetv + 1; w < nvars; ++w )
11708  {
11709  assert(SCIPisIntegral(scip, vals[w]));
11710  }
11711 #endif
11712  SCIPdebugPrintCons(scip, cons, NULL);
11713  }
11714 
11715  /* try to find a better gcd, when having large coefficients */
11716  if( offsetv >= 0 && gcd == 1 )
11717  {
11718  /* calculate greatest common divisor for all general variables */
11719  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11720 
11721  if( gcd > 1 )
11722  {
11723  gcd = -1;
11724  candpos = -1;
11725 
11726  for( v = nvars - 1; v > offsetv; --v )
11727  {
11728  assert(!SCIPisZero(scip, vals[v]));
11729  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11730  break;
11731 
11732  if( !SCIPisIntegral(scip, vals[v]) )
11733  {
11734  allcoefintegral = FALSE;
11735  break;
11736  }
11737 
11738  oldgcd = gcd;
11739 
11740  if( gcd == -1 )
11741  {
11742  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11743  assert(gcd >= 1);
11744  }
11745  else
11746  {
11747  /* calculate greatest common divisor for all general and binary variables */
11748  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11749  }
11750 
11751  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11752  * can stop searching
11753  */
11754  if( gcd == 1 )
11755  {
11756  if( !SCIPvarIsBinary(vars[v]) )
11757  break;
11758 
11759  /* found candidate */
11760  if( candpos == -1 )
11761  {
11762  gcd = oldgcd;
11763  candpos = v;
11764  }
11765  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11766  else
11767  break;
11768  }
11769  }
11770  assert(v > offsetv || candpos > offsetv);
11771  }
11772  else
11773  candpos = -1;
11774  }
11775  else
11776  candpos = nvars - 1;
11777 
11778  /* check last coefficient for integrality */
11779  if( gcd > 1 && allcoefintegral && !redundant )
11780  {
11781  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11782  allcoefintegral = FALSE;
11783  }
11784 
11785  /* check for further necessary coefficient adjustments */
11786  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11787  {
11788  assert(offsetv + 1 < nvars);
11789  assert(0 <= candpos && candpos < nvars);
11790 
11791  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
11792  {
11793  SCIP_Bool notchangable = FALSE;
11794 
11795 #ifndef NDEBUG
11796  /* check integrality */
11797  for( w = offsetv + 1; w < nvars; ++w )
11798  {
11799  assert(SCIPisIntegral(scip, vals[w]));
11800  }
11801 #endif
11802 
11803  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11804  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11805  {
11806  /* determine the remainder of the side and the gcd */
11807  if( hasrhs )
11808  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11809  else
11810  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11811  assert(rest >= 0);
11812  assert(rest < gcd);
11813 
11814  /* determine the remainder of the coefficient candidate and the gcd */
11815  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11816  assert(restcoef >= 1);
11817  assert(restcoef < gcd);
11818 
11819  if( hasrhs )
11820  {
11821  /* calculate new coefficient */
11822  if( restcoef > rest )
11823  newcoef = vals[candpos] - restcoef + gcd;
11824  else
11825  newcoef = vals[candpos] - restcoef;
11826  }
11827  else
11828  {
11829  /* calculate new coefficient */
11830  if( rest == 0 || restcoef < rest )
11831  newcoef = vals[candpos] - restcoef;
11832  else
11833  newcoef = vals[candpos] - restcoef + gcd;
11834  }
11835 
11836 
11837  /* done */
11838 
11839  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11840  * another with the big coefficient was set to 1
11841  */
11842  if( hasrhs && SCIPisZero(scip, newcoef) )
11843  {
11844  notchangable = TRUE;
11845  }
11846  else if( SCIPisZero(scip, newcoef) )
11847  {
11848  /* delete old redundant coefficient */
11849  SCIP_CALL( delCoefPos(scip, cons, candpos) );
11850  ++(*nchgcoefs);
11851  }
11852  else
11853  {
11854  /* replace old with new coefficient */
11855  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11856  ++(*nchgcoefs);
11857  }
11858  }
11859  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11860  {
11861  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11862  }
11863 
11864  /* correct side and big coefficients */
11865  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11866  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11867  {
11868  if( haslhs )
11869  {
11870  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11871 
11872  SCIP_CALL( chgLhs(scip, cons, newcoef) );
11873  ++(*nchgsides);
11874  }
11875  else
11876  {
11877  assert(hasrhs);
11878  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
11879 
11880  SCIP_CALL( chgRhs(scip, cons, newcoef) );
11881  ++(*nchgsides);
11882  }
11883 
11884  /* correct coefficients up front */
11885  for( w = offsetv; w >= 0; --w )
11886  {
11887  assert(vals[w] > 0);
11888 
11889  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
11890  }
11891  (*nchgcoefs) += (offsetv + 1);
11892  }
11893 
11894  if( !notchangable )
11895  {
11896  /* normalize constraint */
11897  SCIP_CALL( normalizeCons(scip, cons) );
11898  assert(vars == consdata->vars);
11899  assert(vals == consdata->vals);
11900 
11901  /* get new constraint data */
11902  nvars = consdata->nvars;
11903  assert(nvars >= 2);
11904 
11905  SCIPdebugPrintCons(scip, cons, NULL);
11906 
11907  lhs = consdata->lhs;
11908  rhs = consdata->rhs;
11909  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11910  assert(!haslhs || !SCIPisNegative(scip, lhs));
11911  }
11912  }
11913  }
11914  }
11915 
11916  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
11917  /* no continuous variables are left over */
11918  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
11919  return SCIP_OKAY;
11920 
11921  onlybin = TRUE;
11922  allcoefintegral = TRUE;
11923  /* check if all variables are of binary type */
11924  for( v = nvars - 1; v >= 0; --v )
11925  {
11926  if( !SCIPvarIsBinary(vars[v]) )
11927  onlybin = FALSE;
11928  if( !SCIPisIntegral(scip, vals[v]) )
11929  allcoefintegral = FALSE;
11930  }
11931 
11932  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
11933  * hand side or bigger than the left hand side respectively, so we can make all of them integral
11934  *
11935  * @todo there are some steps missing ....
11936  */
11937  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
11938  {
11939  SCIP_Real val;
11940  SCIP_Real newval;
11941  SCIP_Real frac = 0.0;
11942  SCIP_Bool found = FALSE;
11943 
11944  if( hasrhs )
11945  {
11946  if( allcoefintegral )
11947  {
11948  /* replace old with new right hand side */
11949  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
11950  ++(*nchgsides);
11951  }
11952  else
11953  {
11954  siderest = rhs - SCIPfloor(scip, rhs);
11955 
11956  /* try to round down all non-integral coefficients */
11957  for( v = nvars - 1; v >= 0; --v )
11958  {
11959  val = vals[v];
11960 
11961  /* add up all possible fractional parts */
11962  if( !SCIPisIntegral(scip, val) )
11963  {
11964  lb = SCIPvarGetLbGlobal(vars[v]);
11965  ub = SCIPvarGetUbGlobal(vars[v]);
11966 
11967  /* at least one bound need to be at zero */
11968  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
11969  return SCIP_OKAY;
11970 
11971  /* swap bounds for 'standard' form */
11972  if( !SCIPisFeasZero(scip, lb) )
11973  {
11974  ub = lb;
11975  val *= -1;
11976  }
11977 
11978  found = TRUE;
11979 
11980  frac += (val - SCIPfloor(scip, val)) * ub;
11981 
11982  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
11983  *
11984  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
11985  * x3, x4 set to 1 would be infeasible but feasible after flooring
11986  */
11987  if( SCIPisGT(scip, frac, siderest) )
11988  return SCIP_OKAY;
11989  }
11990  }
11991  assert(v == -1);
11992 
11993  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
11994 
11995  /* round rhs and coefficients to integral values */
11996  if( found )
11997  {
11998  for( v = nvars - 1; v >= 0; --v )
11999  {
12000  val = vals[v];
12001 
12002  /* add the whole fractional part */
12003  if( !SCIPisIntegral(scip, val) )
12004  {
12005  lb = SCIPvarGetLbGlobal(vars[v]);
12006 
12007  if( SCIPisFeasZero(scip, lb) )
12008  newval = SCIPfloor(scip, val);
12009  else
12010  newval = SCIPceil(scip, val);
12011 
12012  if( SCIPisZero(scip, newval) )
12013  {
12014  /* delete old redundant coefficient */
12015  SCIP_CALL( delCoefPos(scip, cons, v) );
12016  ++(*nchgcoefs);
12017  }
12018  else
12019  {
12020  /* replace old with new coefficient */
12021  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12022  ++(*nchgcoefs);
12023  }
12024  }
12025  }
12026  }
12027 
12028  /* replace old with new right hand side */
12029  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12030  ++(*nchgsides);
12031  }
12032  }
12033  else
12034  {
12035  if( allcoefintegral )
12036  {
12037  /* replace old with new left hand side */
12038  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12039  ++(*nchgsides);
12040  }
12041  else
12042  {
12043  /* cannot floor left hand side to zero */
12044  if( SCIPisLT(scip, lhs, 1.0) )
12045  return SCIP_OKAY;
12046 
12047  siderest = lhs - SCIPfloor(scip, lhs);
12048 
12049  /* try to round down all non-integral coefficients */
12050  for( v = nvars - 1; v >= 0; --v )
12051  {
12052  val = vals[v];
12053 
12054  /* add up all possible fractional parts */
12055  if( !SCIPisIntegral(scip, val) )
12056  {
12057  lb = SCIPvarGetLbGlobal(vars[v]);
12058  ub = SCIPvarGetUbGlobal(vars[v]);
12059 
12060  /* at least one bound need to be at zero */
12061  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12062  return SCIP_OKAY;
12063 
12064  /* swap bounds for 'standard' form */
12065  if( !SCIPisFeasZero(scip, lb) )
12066  {
12067  ub = lb;
12068  val *= -1;
12069  }
12070 
12071  /* cannot floor to zero */
12072  if( SCIPisLT(scip, val, 1.0) )
12073  return SCIP_OKAY;
12074 
12075  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12076  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12077  return SCIP_OKAY;
12078 
12079  found = TRUE;
12080 
12081  frac += (val - SCIPfloor(scip, val)) * ub;
12082 
12083  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12084  * fractional parts of the variables, we cannot tighten the coefficients
12085  *
12086  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12087  * x2-x4 set to 1 would be feasible but not after flooring
12088  */
12089  if( SCIPisGE(scip, frac, 1 + siderest) )
12090  return SCIP_OKAY;
12091  }
12092  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12093  else
12094  return SCIP_OKAY;
12095  }
12096  assert(v == -1);
12097 
12098  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12099 
12100  /* round lhs and coefficients to integral values */
12101  if( found )
12102  {
12103  for( v = nvars - 1; v >= 0; --v )
12104  {
12105  val = vals[v];
12106 
12107  /* add the whole fractional part */
12108  if( !SCIPisIntegral(scip, val) )
12109  {
12110  lb = SCIPvarGetLbGlobal(vars[v]);
12111 
12112  if( SCIPisFeasZero(scip, lb) )
12113  newval = SCIPfloor(scip, val);
12114  else
12115  newval = SCIPceil(scip, val);
12116 
12117  if( SCIPisZero(scip, newval) )
12118  {
12119  /* delete old redundant coefficient */
12120  SCIP_CALL( delCoefPos(scip, cons, v) );
12121  ++(*nchgcoefs);
12122  }
12123  else
12124  {
12125  /* replace old with new coefficient */
12126  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12127  ++(*nchgcoefs);
12128  }
12129  }
12130  }
12131  }
12132 
12133  /* replace old with new left hand side */
12134  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12135  ++(*nchgsides);
12136  }
12137  }
12138 
12139  /* normalize constraint */
12140  SCIP_CALL( normalizeCons(scip, cons) );
12141  assert(vars == consdata->vars);
12142  assert(vals == consdata->vals);
12143 
12144  rhs = consdata->rhs;
12145  lhs = consdata->lhs;
12146 
12147  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12148  assert(!haslhs || !SCIPisNegative(scip, lhs));
12149 
12150  SCIPdebugPrintCons(scip, cons, NULL);
12151 
12152  nvars = consdata->nvars;
12153  if( nvars < 2 )
12154  return SCIP_OKAY;
12155 
12156  allcoefintegral = TRUE;
12157 #ifndef NDEBUG
12158  /* debug check if all coefficients are really integral */
12159  for( v = nvars - 1; v >= 0; --v )
12160  assert(SCIPisIntegral(scip, vals[v]));
12161 #endif
12162  }
12163 
12164  /* @todo following can also work on non integral coefficients, need more investigation */
12165  /* only check constraints with integral coefficients on all integral variables */
12166  if( !allcoefintegral )
12167  return SCIP_OKAY;
12168 
12169  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12170  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12171  return SCIP_OKAY;
12172 
12173  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12174  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12175  return SCIP_OKAY;
12176 
12177  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12178  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12179  return SCIP_OKAY;
12180 
12181  assert(nvars >= 2);
12182 
12183  /* start gcd procedure for all variables */
12184  do
12185  {
12186  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12187  SCIPdebug( oldnchgsides = *nchgsides; )
12188 
12189  /* stop if we have two coeffcients which are one in absolute value */
12190  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12191  return SCIP_OKAY;
12192 
12193  gcd = -1;
12194 
12195  /* calculate greatest common divisor over all integer variables */
12196  if( !onlybin )
12197  {
12198  foundbin = -1;
12199 
12200  for( v = nvars - 1; v >= 0; --v )
12201  {
12202  assert(!SCIPisZero(scip, vals[v]));
12203  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12204 
12205  if( SCIPvarIsBinary(vars[v]) )
12206  {
12207  if( foundbin == -1 )
12208  foundbin = v;
12209  continue;
12210  }
12211 
12212  absval = REALABS(vals[v]);
12213  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12214  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12215  */
12216  assert(SCIPisFeasIntegral(scip, absval));
12217 
12218  if( gcd == -1 )
12219  {
12220  gcd = (SCIP_Longint)(absval + feastol);
12221  assert(gcd >= 1);
12222  }
12223  else
12224  {
12225  /* calculate greatest common divisor for all general variables */
12226  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12227  }
12228  if( gcd == 1 )
12229  break;
12230  }
12231  }
12232  else
12233  foundbin = nvars - 1;
12234 
12235  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12236  if( gcd == 1 || foundbin == -1)
12237  return SCIP_OKAY;
12238 
12239  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12240 
12241  candpos = -1;
12242  candpos2 = -1;
12243 
12244  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12245  * change the coefficient
12246  */
12247  for( v = foundbin; v >= 0; --v )
12248  {
12249  if( onlybin || SCIPvarIsBinary(vars[v]) )
12250  {
12251  absval = REALABS(vals[v]);
12252  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12253  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12254  */
12255  assert(SCIPisFeasIntegral(scip, absval));
12256 
12257  oldgcd = gcd;
12258 
12259  if( gcd == -1 )
12260  {
12261  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12262  assert(gcd >= 1);
12263  }
12264  else
12265  {
12266  /* calculate greatest common divisor for all general and binary variables */
12267  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12268  }
12269 
12270  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12271  * can terminate
12272  */
12273  if( gcd == 1 )
12274  {
12275  /* found candidate */
12276  if( candpos == -1 )
12277  {
12278  gcd = oldgcd;
12279  candpos = v;
12280 
12281  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12282  * the coefficient change
12283  */
12284  if( onlybin && v == foundbin - 1 )
12285  candpos2 = foundbin;
12286  }
12287  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12288  else
12289  {
12290  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12291  {
12292  assert(candpos2 == nvars - 1);
12293 
12294  /* take new candidates */
12295  candpos = candpos2;
12296 
12297  /* recalculate gcd from scratch */
12298  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12299  assert(gcd >= 1);
12300 
12301  /* calculate greatest common divisor for all general and binary variables */
12302  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12303  if( gcd == 1 )
12304  return SCIP_OKAY;
12305  }
12306  else
12307  /* cannot determine a possible coefficient for reduction */
12308  return SCIP_OKAY;
12309  }
12310  }
12311  }
12312  }
12313  assert(gcd >= 2);
12314 
12315  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12316  * further
12317  */
12318  assert(candpos >= 0 && candpos < nvars);
12319 
12320  /* all variables and all coefficients are integral, so the side should be too */
12321  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12322 
12323  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12324  * @see normalizeCons()
12325  */
12326  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12327  assert(!haslhs || !SCIPisNegative(scip, lhs));
12328 
12329  /* determine the remainder of the side and the gcd */
12330  if( hasrhs )
12331  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12332  else
12333  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12334  assert(rest >= 0);
12335  assert(rest < gcd);
12336 
12337  /* determine the remainder of the coefficient candidate and the gcd */
12338  if( vals[candpos] < 0 )
12339  {
12340  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12341  assert(restcoef <= -1);
12342  restcoef += gcd;
12343  }
12344  else
12345  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12346  assert(restcoef >= 1);
12347  assert(restcoef < gcd);
12348 
12349  if( hasrhs )
12350  {
12351  if( rest > 0 )
12352  {
12353  /* replace old with new right hand side */
12354  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12355  ++(*nchgsides);
12356  }
12357 
12358  /* calculate new coefficient */
12359  if( restcoef > rest )
12360  newcoef = vals[candpos] - restcoef + gcd;
12361  else
12362  newcoef = vals[candpos] - restcoef;
12363  }
12364  else
12365  {
12366  if( rest > 0 )
12367  {
12368  /* replace old with new left hand side */
12369  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12370  ++(*nchgsides);
12371  }
12372 
12373  /* calculate new coefficient */
12374  if( rest == 0 || restcoef < rest )
12375  newcoef = vals[candpos] - restcoef;
12376  else
12377  newcoef = vals[candpos] - restcoef + gcd;
12378  }
12379  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12380 
12381  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));
12382 
12383  if( SCIPisZero(scip, newcoef) )
12384  {
12385  /* delete redundant coefficient */
12386  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12387  }
12388  else
12389  {
12390  /* replace old with new coefficient */
12391  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12392  }
12393  ++(*nchgcoefs);
12394 
12395  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12396  SCIP_CALL( normalizeCons(scip, cons) );
12397  assert(vars == consdata->vars);
12398  assert(vals == consdata->vals);
12399 
12400  SCIPdebugPrintCons(scip, cons, NULL);
12401 
12402  rhs = consdata->rhs;
12403  lhs = consdata->lhs;
12404  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12405  assert(!haslhs || !SCIPisNegative(scip, lhs));
12406 
12407  nvars = consdata->nvars;
12408 
12409  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));
12410  }
12411  while( nvars >= 2 );
12412 
12413  return SCIP_OKAY;
12414 }
12415 
12416 
12417 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12418  * cons0 := a * cons0 + b * cons1,
12419  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12420  * for numerical stability, we will only accept integral a and b;
12421  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12422  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12423  */
12424 static
12426  SCIP* scip, /**< SCIP data structure */
12427  SCIP_CONS* cons0, /**< (in)equality to modify */
12428  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12429  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12430  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12431  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12432  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12433  int nvarscommon, /**< number of variables, that appear in both constraints */
12434  int commonidxweight, /**< variable weight sum of common variables */
12435  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12436  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12437  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12438  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12439  SCIP_Bool* aggregated /**< pointer to store whether an aggregation was made */
12440  )
12441 {
12442  SCIP_CONSDATA* consdata0;
12443  SCIP_CONSDATA* consdata1;
12444  SCIP_Real a;
12445  SCIP_Real b;
12446  SCIP_Real aggrcoef;
12447  SCIP_Real scalarsum;
12448  SCIP_Real bestscalarsum;
12449  SCIP_Bool betterscalarsum;
12450  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12451  int varweight;
12452  int nvars;
12453  int bestvarweight;
12454  int bestnvars;
12455  int bestv;
12456  int v;
12457  int i;
12458 
12459  assert(scip != NULL);
12460  assert(cons0 != NULL);
12461  assert(cons1 != NULL);
12462  assert(commonidx0 != NULL);
12463  assert(commonidx1 != NULL);
12464  assert(diffidx0minus1 != NULL);
12465  assert(diffidx1minus0 != NULL);
12466  assert(nvarscommon >= 1);
12467  assert(commonidxweight >= nvarscommon);
12468  assert(nchgcoefs != NULL);
12469  assert(aggregated != NULL);
12470 
12471  assert(SCIPconsIsActive(cons0));
12472  assert(SCIPconsIsActive(cons1));
12473 
12474  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12475 
12476  /* cons0 is an (in)equality */
12477  consdata0 = SCIPconsGetData(cons0);
12478  assert(consdata0 != NULL);
12479  assert(consdata0->nvars >= 1);
12480  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12481  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12482 
12483  /* cons1 is an equality */
12484  consdata1 = SCIPconsGetData(cons1);
12485  assert(consdata1 != NULL);
12486  assert(consdata1->nvars >= 1);
12487  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12488  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12489 
12490  *aggregated = FALSE;
12491 
12492  /* search for the best common variable such that
12493  * val1[var] * consdata0 - val0[var] * consdata1
12494  * has least weighted number of variables
12495  */
12496  bestvarweight = commonidxweight + diffidx0minus1weight;
12497  bestnvars = consdata0->nvars;
12498  bestv = -1;
12499  bestscalarsum = 0.0;
12500  commonvarlindependent = TRUE;
12501  for( v = 0; v < nvarscommon; ++v )
12502  {
12503  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12504  a = consdata1->vals[commonidx1[v]];
12505  b = -consdata0->vals[commonidx0[v]];
12506 
12507  /* only try aggregation, if coefficients are integral (numerical stability) */
12508  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12509  {
12510  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12511  varweight = diffidx0minus1weight + diffidx1minus0weight;
12512  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12513  scalarsum = REALABS(a) + REALABS(b);
12514  betterscalarsum = (scalarsum < bestscalarsum);
12515  for( i = 0; i < nvarscommon
12516  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12517  {
12518  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12519  if( !SCIPisZero(scip, aggrcoef) )
12520  {
12521  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12522  nvars++;
12523  }
12524  }
12525  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12526  {
12527  bestv = v;
12528  bestvarweight = varweight;
12529  bestnvars = nvars;
12530  bestscalarsum = scalarsum;
12531  }
12532  }
12533 
12534  /* update commonvarlindependent flag, if still TRUE:
12535  * 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
12536  */
12537  if( commonvarlindependent && v > 0 )
12538  commonvarlindependent = SCIPisEQ(scip,
12539  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12540  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12541  }
12542 
12543  /* if better aggregation was found, create new constraint and delete old one */
12544  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12545  {
12546  SCIP_CONS* newcons;
12547  SCIP_CONSDATA* newconsdata;
12548  SCIP_VAR** newvars;
12549  SCIP_Real* newvals;
12550  SCIP_Real newlhs;
12551  SCIP_Real newrhs;
12552  int newnvars;
12553 
12554  if( bestv != -1 )
12555  {
12556  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12557  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12558  {
12559  a = consdata1->vals[commonidx1[bestv]];
12560  b = -consdata0->vals[commonidx0[bestv]];
12561  }
12562  else
12563  {
12564  a = -consdata1->vals[commonidx1[bestv]];
12565  b = consdata0->vals[commonidx0[bestv]];
12566  }
12567  assert(SCIPisIntegral(scip, a));
12568  assert(SCIPisPositive(scip, a));
12569  assert(SCIPisIntegral(scip, b));
12570  assert(!SCIPisZero(scip, b));
12571  }
12572  else
12573  {
12574  assert(commonvarlindependent);
12575  if( consdata1->vals[commonidx1[0]] > 0.0 )
12576  {
12577  a = consdata1->vals[commonidx1[0]];
12578  b = -consdata0->vals[commonidx0[0]];
12579  }
12580  else
12581  {
12582  a = -consdata1->vals[commonidx1[0]];
12583  b = consdata0->vals[commonidx0[0]];
12584  }
12585  assert(SCIPisPositive(scip, a));
12586  assert(!SCIPisZero(scip, b));
12587 
12588  /* if a/b is integral, then we can easily choose integer multipliers */
12589  if( SCIPisIntegral(scip, a/b) )
12590  {
12591  if( a/b > 0 )
12592  {
12593  a /= b;
12594  b = 1.0;
12595  }
12596  else
12597  {
12598  a /= -b;
12599  b = -1.0;
12600  }
12601  }
12602 
12603  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12604  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12605  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12606  }
12607 
12608  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12609  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12610  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12611  SCIPdebugPrintCons(scip, cons0, NULL);
12612  SCIPdebugPrintCons(scip, cons1, NULL);
12613 
12614  /* get temporary memory for creating the new linear constraint */
12615  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12616  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12617 
12618  /* calculate the common coefficients, if we have not recognized linear dependency */
12619  newnvars = 0;
12620  if( !commonvarlindependent )
12621  {
12622  for( i = 0; i < nvarscommon; ++i )
12623  {
12624  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12625  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12626 
12627  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12628  if( !SCIPisZero(scip, aggrcoef) )
12629  {
12630  assert(newnvars < bestnvars);
12631  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12632  newvals[newnvars] = aggrcoef;
12633  newnvars++;
12634  }
12635  }
12636  }
12637  else
12638  {
12639  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12640 #ifndef NDEBUG
12641  for( i = 0; i < nvarscommon; ++i )
12642  {
12643  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12644  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12645 
12646  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12647  assert(SCIPisZero(scip, aggrcoef));
12648  }
12649 #endif
12650  }
12651 
12652  /* calculate the coefficients appearing in cons0 but not in cons1 */
12653  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12654  {
12655  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12656 
12657  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12658  assert(!SCIPisZero(scip, aggrcoef));
12659  assert(newnvars < bestnvars);
12660  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12661  newvals[newnvars] = aggrcoef;
12662  newnvars++;
12663  }
12664 
12665  /* calculate the coefficients appearing in cons1 but not in cons0 */
12666  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12667  {
12668  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12669 
12670  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12671  assert(!SCIPisZero(scip, aggrcoef));
12672  assert(newnvars < bestnvars);
12673  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12674  newvals[newnvars] = aggrcoef;
12675  newnvars++;
12676  }
12677  assert(newnvars == bestnvars);
12678 
12679  /* calculate the new left and right hand side of the (in)equality */
12680  assert(!SCIPisInfinity(scip, -consdata1->lhs));
12681  assert(!SCIPisInfinity(scip, consdata1->rhs));
12682  if( SCIPisInfinity(scip, -consdata0->lhs) )
12683  newlhs = -SCIPinfinity(scip);
12684  else
12685  newlhs = a * consdata0->lhs + b * consdata1->lhs;
12686  if( SCIPisInfinity(scip, consdata0->rhs) )
12687  newrhs = SCIPinfinity(scip);
12688  else
12689  newrhs = a * consdata0->rhs + b * consdata1->rhs;
12690 
12691  /* create the new linear constraint */
12692  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12694  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12695  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12697 
12698  newconsdata = SCIPconsGetData(newcons);
12699  assert(newconsdata != NULL);
12700 
12701  /* copy the upgraded flag from the old cons0 to the new constraint */
12702  newconsdata->upgraded = consdata0->upgraded;
12703 
12704  /* normalize the new constraint */
12705  SCIP_CALL( normalizeCons(scip, newcons) );
12706 
12707  /* check, if we really want to use the new constraint instead of the old one:
12708  * use the new one, if the maximum norm doesn't grow too much
12709  */
12710  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12711  {
12712  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12713  SCIPdebugPrintCons(scip, newcons, NULL);
12714 
12715  /* update the statistics: we changed all coefficients */
12716  if( !consdata0->upgraded )
12717  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12718  *aggregated = TRUE;
12719 
12720  /* delete the old constraint, and add the new linear constraint to the problem */
12721  SCIP_CALL( SCIPdelCons(scip, cons0) );
12722  SCIP_CALL( SCIPaddCons(scip, newcons) );
12723  }
12724 
12725  /* release the new constraint */
12726  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12727 
12728  /* free temporary memory */
12729  SCIPfreeBufferArray(scip, &newvals);
12730  SCIPfreeBufferArray(scip, &newvars);
12731  }
12732 
12733  return SCIP_OKAY;
12734 }
12735 
12736 /** gets the key of the given element */
12737 static
12738 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12739 { /*lint --e{715}*/
12740  /* the key is the element itself */
12741  return elem;
12742 }
12743 
12744 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12745  * coefficients are either equal or negated
12746  */
12747 static
12748 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12749 {
12750  SCIP* scip;
12751  SCIP_CONSDATA* consdata1;
12752  SCIP_CONSDATA* consdata2;
12753  SCIP_Real cons1scale;
12754  SCIP_Real cons2scale;
12755  int i;
12756 
12757  assert(key1 != NULL);
12758  assert(key2 != NULL);
12759  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12760  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12761  assert(consdata1->sorted);
12762  assert(consdata2->sorted);
12763 
12764  scip = (SCIP*)userptr;
12765  assert(scip != NULL);
12766 
12767  /* if it is the same constraint we dont need to check anything */
12768  if( key1 == key2 )
12769  return TRUE;
12770 
12771  /* checks trivial case */
12772  if( consdata1->nvars != consdata2->nvars )
12773  return FALSE;
12774 
12775  /* tests if variables are equal */
12776  for( i = 0; i < consdata1->nvars; ++i )
12777  {
12778  if( consdata1->vars[i] != consdata2->vars[i] )
12779  {
12780  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12781  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12782  return FALSE;
12783  }
12784  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12785  }
12786 
12787  /* compute scale before comparing coefficients of constraints */
12788  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
12789  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
12790 
12791  /* tests if coefficients are equal with the computed scale */
12792  for( i = 0; i < consdata1->nvars; ++i )
12793  {
12794  SCIP_Real val1;
12795  SCIP_Real val2;
12796 
12797  val1 = consdata1->vals[i] * cons1scale;
12798  val2 = consdata2->vals[i] * cons2scale;
12799 
12800  if( !SCIPisEQ(scip, val1, val2) )
12801  return FALSE;
12802  }
12803 
12804  return TRUE;
12805 }
12806 
12807 /** returns the hash value of the key */
12808 static
12809 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12810 {
12811  SCIP_CONSDATA* consdata;
12812  int minidx;
12813  int mididx;
12814  int maxidx;
12815  SCIP_Real scale;
12816 #ifndef NDEBUG
12817  SCIP* scip;
12818 
12819  scip = (SCIP*)userptr;
12820  assert(scip != NULL);
12821 #endif
12822 
12823  assert(key != NULL);
12824  consdata = SCIPconsGetData((SCIP_CONS*)key);
12825  assert(consdata != NULL);
12826  assert(consdata->nvars > 0);
12827 
12828  assert(consdata->sorted);
12829 
12830  minidx = SCIPvarGetIndex(consdata->vars[0]);
12831  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12832  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12833  assert(minidx >= 0 && minidx <= maxidx);
12834  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
12835 
12836  /* using only the variable indices as hash, since the values are compared by epsilon */
12837  return SCIPhashFour(consdata->nvars,
12838  SCIPcombineTwoInt(minidx, SCIPrealHashCode(consdata->vals[0] * scale)),
12839  SCIPcombineTwoInt(mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale)),
12840  SCIPcombineTwoInt(maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale))); /*lint !e571*/
12841 }
12842 
12843 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12844  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12845  */
12846 static
12847 unsigned int getParallelConsKey(
12848  SCIP_CONS* cons /**< linear constraint */
12849  )
12850 {
12851  SCIP_CONSDATA* consdata;
12852 
12853  assert(cons != NULL);
12854 
12855  consdata = SCIPconsGetData(cons);
12856  assert(consdata != NULL);
12857 
12858  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
12859 }
12860 
12861 /** updates the hashtable such that out of all constraints in the hashtable that are detected
12862  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
12863  * and all others are removed from the hashtable and stored in the given array
12864  */
12865 static
12867  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
12868  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
12869  * upon return will contain the constraint that should be kept */
12870  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
12871  * these constraints where removed from the hashtable */
12872  int* nparallelconss /**< pointer to return number of parallel constraints */
12873  )
12874 {
12875  SCIP_CONS* parallelcons;
12876  unsigned int querykey;
12877 
12878  *nparallelconss = 0;
12879  querykey = getParallelConsKey(*querycons);
12880 
12881  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
12882  {
12883  unsigned int conskey = getParallelConsKey(parallelcons);
12884 
12885  if( conskey < querykey )
12886  {
12887  parallelconss[(*nparallelconss)++] = *querycons;
12888  *querycons = parallelcons;
12889  querykey = conskey;
12890  }
12891  else
12892  {
12893  parallelconss[(*nparallelconss)++] = parallelcons;
12894  }
12895 
12896  /* if the constraint that just came out of the hash table is the one that is kept,
12897  * we do not need to look into the hashtable again, since the invariant is that
12898  * in the hashtable only pair-wise non-parallel constraints are contained.
12899  * For the original querycons, however, multiple constraints that compare equal (=parallel)
12900  * could be contained due to non-transitivity of the equality comparison.
12901  * Also we can return immediately, since parallelcons is already contained in the
12902  * hashtable and we do not need to remove and reinsert it.
12903  */
12904  if( *querycons == parallelcons )
12905  return SCIP_OKAY;
12906 
12907  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
12908  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
12909  }
12910 
12911  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
12912  * comnpares equal to querycons at this point
12913  */
12914 #ifndef NDEBUG
12915  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
12916 #else
12917  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
12918 #endif
12919 
12920  return SCIP_OKAY;
12921 }
12922 
12923 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
12924  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
12925  */
12926 static
12928  SCIP* scip, /**< SCIP data structure */
12929  BMS_BLKMEM* blkmem, /**< block memory */
12930  SCIP_CONS** conss, /**< constraint set */
12931  int nconss, /**< number of constraints in constraint set */
12932  int* firstchange, /**< pointer to store first changed constraint */
12933  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
12934  int* ndelconss, /**< pointer to count number of deleted constraints */
12935  int* nchgsides /**< pointer to count number of changed left/right hand sides */
12936  )
12937 {
12938  SCIP_HASHTABLE* hashtable;
12939  SCIP_CONS** parallelconss;
12940  int nparallelconss;
12941  int hashtablesize;
12942  int c;
12943 
12944  assert(scip != NULL);
12945  assert(blkmem != NULL);
12946  assert(conss != NULL);
12947  assert(firstchange != NULL);
12948  assert(cutoff != NULL);
12949  assert(ndelconss != NULL);
12950  assert(nchgsides != NULL);
12951 
12952  /* create a hash table for the constraint set */
12953  hashtablesize = nconss;
12954  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
12955  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
12956 
12957  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
12958 
12959  /* check all constraints in the given set for redundancy */
12960  for( c = 0; c < nconss; ++c )
12961  {
12962  SCIP_CONS* cons0;
12963  SCIP_CONSDATA* consdata0;
12964 
12965  cons0 = conss[c];
12966 
12967  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
12968  continue;
12969 
12970  /* check for interuption */
12971  if( c % 1000 == 0 && SCIPisStopped(scip) )
12972  break;
12973 
12974  /* sorts the constraint */
12975  consdata0 = SCIPconsGetData(cons0);
12976  assert(consdata0 != NULL);
12977  SCIP_CALL( consdataSort(scip, consdata0) );
12978  assert(consdata0->sorted);
12979 
12980  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
12981  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
12982  * first variable is positive
12983  * Also inserts cons0 into the hashtable.
12984  */
12985  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
12986 
12987  if( nparallelconss != 0 )
12988  {
12989  SCIP_Real lhs;
12990  SCIP_Real rhs;
12991 
12992  int i;
12993 
12994  /* cons0 may have been changed in retrieveParallelConstraints() */
12995  consdata0 = SCIPconsGetData(cons0);
12996 
12997  lhs = consdata0->lhs;
12998  rhs = consdata0->rhs;
12999 
13000  for( i = 0; i < nparallelconss; ++i )
13001  {
13002  SCIP_CONS* consdel;
13003  SCIP_CONSDATA* consdatadel;
13004  SCIP_Real scale;
13005 
13006  consdel = parallelconss[i];
13007  consdatadel = SCIPconsGetData(consdel);
13008 
13009  assert(SCIPconsIsActive(consdel));
13010  assert(!SCIPconsIsModifiable(consdel));
13011 
13012  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13013  * delete old constraints afterwards
13014  */
13015  assert(consdatadel != NULL);
13016  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13017 
13018  assert(consdatadel->sorted);
13019  assert(consdata0->vars[0] == consdatadel->vars[0]);
13020 
13021  scale = consdata0->vals[0] / consdatadel->vals[0];
13022  assert(scale != 0.0);
13023 
13024  /* in debug mode, check that all coefficients are equal with respect to epsilon
13025  * if the constraints are in equilibrium scale
13026  */
13027 #ifndef NDEBUG
13028  {
13029  int k;
13030  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13031  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13032 
13033  for( k = 0; k < consdata0->nvars; ++k )
13034  {
13035  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13036  }
13037  }
13038 #endif
13039 
13040  if( scale > 0.0 )
13041  {
13042  /* the coefficients of both constraints are parallel with a positive scale */
13043  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13044  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13045  SCIPdebugPrintCons(scip, cons0, NULL);
13046  SCIPdebugPrintCons(scip, consdel, NULL);
13047 
13048  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13049  lhs = MAX(scale * consdatadel->lhs, lhs);
13050 
13051  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13052  rhs = MIN(scale * consdatadel->rhs, rhs);
13053  }
13054  else
13055  {
13056  /* the coefficients of both rows are negations */
13057  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13058  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13059  SCIPdebugPrintCons(scip, cons0, NULL);
13060  SCIPdebugPrintCons(scip, consdel, NULL);
13061 
13062  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13063  lhs = MAX(scale * consdatadel->rhs, lhs);
13064 
13065  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13066  rhs = MIN(scale * consdatadel->lhs, rhs);
13067  }
13068 
13069  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13070  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13071 
13072  /* delete consdel */
13073  assert( ! consdata0->upgraded || consdatadel->upgraded );
13074  SCIP_CALL( SCIPdelCons(scip, consdel) );
13075  if( !consdatadel->upgraded )
13076  (*ndelconss)++;
13077  }
13078 
13079  if( SCIPisFeasLT(scip, rhs, lhs) )
13080  {
13081  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13082  *cutoff = TRUE;
13083  break;
13084  }
13085 
13086  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13087  if( lhs > rhs )
13088  {
13089  rhs = (lhs + rhs)/2;
13090  lhs = rhs;
13091  }
13092 
13093  /* update lhs and rhs of cons0 */
13094  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13095  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13096 
13097  /* update the first changed constraint to begin the next aggregation round with */
13098  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13099  *firstchange = SCIPconsGetPos(cons0);
13100 
13101  assert(SCIPconsIsActive(cons0));
13102  }
13103  }
13104 #ifdef SCIP_MORE_DEBUG
13105  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13107 #endif
13108 
13109  SCIPfreeBufferArray(scip, &parallelconss);
13110 
13111  /* free hash table */
13112  SCIPhashtableFree(&hashtable);
13113 
13114  return SCIP_OKAY;
13115 }
13116 
13117 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13118  * and removes or changes constraint accordingly
13119  */
13120 static
13122  SCIP* scip, /**< SCIP data structure */
13123  SCIP_CONS** conss, /**< constraint set */
13124  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13125  int chkind, /**< index of constraint to check against all prior indices upto startind */
13126  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13127  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13128  int* ndelconss, /**< pointer to count number of deleted constraints */
13129  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13130  int* nchgcoefs /**< pointer to count number of changed coefficients */
13131  )
13132 {
13133  SCIP_CONS* cons0;
13134  SCIP_CONSDATA* consdata0;
13135  int* commonidx0;
13136  int* commonidx1;
13137  int* diffidx0minus1;
13138  int* diffidx1minus0;
13139  uint64_t possignature0;
13140  uint64_t negsignature0;
13141  SCIP_Bool cons0changed;
13142  SCIP_Bool cons0isequality;
13143  int diffidx1minus0size;
13144  int c;
13145  SCIP_Real cons0lhs;
13146  SCIP_Real cons0rhs;
13147  SCIP_Bool cons0upgraded;
13148 
13149  assert(scip != NULL);
13150  assert(conss != NULL);
13151  assert(firstchange <= chkind);
13152  assert(cutoff != NULL);
13153  assert(ndelconss != NULL);
13154  assert(nchgsides != NULL);
13155  assert(nchgcoefs != NULL);
13156 
13157  /* get the constraint to be checked against all prior constraints */
13158  cons0 = conss[chkind];
13159  assert(cons0 != NULL);
13160  assert(SCIPconsIsActive(cons0));
13161  assert(!SCIPconsIsModifiable(cons0));
13162 
13163  consdata0 = SCIPconsGetData(cons0);
13164  assert(consdata0 != NULL);
13165  assert(consdata0->nvars >= 1);
13166  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13167 
13168  /* sort the constraint */
13169  SCIP_CALL( consdataSort(scip, consdata0) );
13170 
13171  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13172  consdataCalcSignatures(consdata0);
13173  possignature0 = consdata0->possignature;
13174  negsignature0 = consdata0->negsignature;
13175 
13176  /* get temporary memory for indices of common variables */
13177  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13178  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13179  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13180  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13181  diffidx1minus0size = consdata0->nvars;
13182 
13183  cons0lhs = consdata0->lhs;
13184  cons0rhs = consdata0->rhs;
13185  cons0upgraded = consdata0->upgraded;
13186 
13187  /* check constraint against all prior constraints */
13188  cons0changed = consdata0->changed;
13189  consdata0->changed = FALSE;
13190  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13191  {
13192  SCIP_CONS* cons1;
13193  SCIP_CONSDATA* consdata1;
13194  uint64_t possignature1;
13195  uint64_t negsignature1;
13196  SCIP_Bool cons0dominateslhs;
13197  SCIP_Bool cons1dominateslhs;
13198  SCIP_Bool cons0dominatesrhs;
13199  SCIP_Bool cons1dominatesrhs;
13200  SCIP_Bool cons1isequality;
13201  SCIP_Bool coefsequal;
13202  SCIP_Bool coefsnegated;
13203  SCIP_Bool tryaggregation;
13204  int nvarscommon;
13205  int nvars0minus1;
13206  int nvars1minus0;
13207  int commonidxweight;
13208  int diffidx0minus1weight;
13209  int diffidx1minus0weight;
13210  int v0;
13211  int v1;
13212 
13213  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13214  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13215  assert(cons0upgraded == consdata0->upgraded);
13216 
13217  cons1 = conss[c];
13218 
13219  /* cons1 has become inactive during presolving of constraint pairs */
13220  if( cons1 == NULL )
13221  continue;
13222 
13223  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13224  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13225 
13226  consdata1 = SCIPconsGetData(cons1);
13227  assert(consdata1 != NULL);
13228 
13229  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13230  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13231  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13232 
13233  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13234  if( !cons0changed && !consdata1->changed )
13235  continue;
13236 
13237  /* if both constraints are already upgraded, skip the pair;
13238  * because changes on these constraints cannot be applied to the instance anymore */
13239  if( cons0upgraded && consdata1->upgraded )
13240  continue;
13241 
13242  assert(consdata1->nvars >= 1);
13243 
13244  /* sort the constraint */
13245  SCIP_CALL( consdataSort(scip, consdata1) );
13246 
13247  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13248  consdataCalcSignatures(consdata1);
13249  possignature1 = consdata1->possignature;
13250  negsignature1 = consdata1->negsignature;
13251 
13252  /* the signatures give a quick test to check for domination and equality of coefficients */
13253  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13254  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13255  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13256  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13257  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13258  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13259  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13260  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13261  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13262  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13263  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13264  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13265  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13266  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13267  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13268  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13269  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13270  && !coefsequal && !coefsnegated && !tryaggregation )
13271  continue;
13272 
13273  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13274  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13275  {
13276  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13277  diffidx1minus0size = consdata1->nvars;
13278  }
13279 
13280  /* check consdata0 against consdata1:
13281  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13282  * consdata0 dominates consdata1 w.r.t. left hand side
13283  * - if rhs0 <= rhs1 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. right hand side
13285  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13286  * ranged row (or equality)
13287  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13288  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13289  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13290  * number of continuous and integer variables are preferred:
13291  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13292  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13293  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13294  * to be positive to not switch the sense of the (in)equality cons0
13295  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13296  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13297  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13298  * to be positive to not switch the sense of the (in)equality cons1
13299  */
13300 
13301  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13302  nvarscommon = 0;
13303  commonidxweight = 0;
13304  nvars0minus1 = 0;
13305  diffidx0minus1weight = 0;
13306  nvars1minus0 = 0;
13307  diffidx1minus0weight = 0;
13308  v0 = 0;
13309  v1 = 0;
13310  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13311  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13312  || coefsequal || coefsnegated || tryaggregation) )
13313  {
13314  SCIP_VAR* var;
13315  SCIP_Real val0;
13316  SCIP_Real val1;
13317  int varcmp;
13318 
13319  /* test, if variable appears in only one or in both constraints */
13320  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13321  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13322  else if( v0 < consdata0->nvars )
13323  varcmp = -1;
13324  else
13325  varcmp = +1;
13326 
13327  switch( varcmp )
13328  {
13329  case -1:
13330  /* variable doesn't appear in consdata1 */
13331  var = consdata0->vars[v0];
13332  val0 = consdata0->vals[v0];
13333  val1 = 0.0;
13334  if( tryaggregation )
13335  {
13336  diffidx0minus1[nvars0minus1] = v0;
13337  nvars0minus1++;
13338  diffidx0minus1weight += getVarWeight(var);
13339  }
13340  v0++;
13341  coefsequal = FALSE;
13342  coefsnegated = FALSE;
13343  break;
13344 
13345  case +1:
13346  /* variable doesn't appear in consdata0 */
13347  var = consdata1->vars[v1];
13348  val0 = 0.0;
13349  val1 = consdata1->vals[v1];
13350  if( tryaggregation )
13351  {
13352  diffidx1minus0[nvars1minus0] = v1;
13353  nvars1minus0++;
13354  diffidx1minus0weight += getVarWeight(var);
13355  }
13356  v1++;
13357  coefsequal = FALSE;
13358  coefsnegated = FALSE;
13359  break;
13360 
13361  case 0:
13362  /* variable appears in both constraints */
13363  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13364  var = consdata0->vars[v0];
13365  val0 = consdata0->vals[v0];
13366  val1 = consdata1->vals[v1];
13367  if( tryaggregation )
13368  {
13369  commonidx0[nvarscommon] = v0;
13370  commonidx1[nvarscommon] = v1;
13371  nvarscommon++;
13372  commonidxweight += getVarWeight(var);
13373  }
13374  v0++;
13375  v1++;
13376  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13377  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13378  break;
13379 
13380  default:
13381  SCIPerrorMessage("invalid comparison result\n");
13382  SCIPABORT();
13383  var = NULL;
13384  val0 = 0.0;
13385  val1 = 0.0;
13386  }
13387  assert(var != NULL);
13388 
13389  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13390  if( SCIPisGT(scip, val0, val1) )
13391  {
13392  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13393  {
13394  cons0dominatesrhs = FALSE;
13395  cons1dominateslhs = FALSE;
13396  }
13397  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13398  {
13399  cons0dominateslhs = FALSE;
13400  cons1dominatesrhs = FALSE;
13401  }
13402  }
13403  else if( SCIPisLT(scip, val0, val1) )
13404  {
13405  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13406  {
13407  cons0dominateslhs = FALSE;
13408  cons1dominatesrhs = FALSE;
13409  }
13410  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13411  {
13412  cons0dominatesrhs = FALSE;
13413  cons1dominateslhs = FALSE;
13414  }
13415  }
13416  }
13417 
13418  /* check for disaggregated ranged rows */
13419  if( coefsequal || coefsnegated )
13420  {
13421  SCIP_CONS* consstay;
13422  SCIP_CONS* consdel;
13423 #ifndef NDEBUG
13424  SCIP_CONSDATA* consdatastay;
13425 #endif
13426  SCIP_CONSDATA* consdatadel;
13427  SCIP_Real lhs;
13428  SCIP_Real rhs;
13429  int consinddel;
13430 
13431  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13432  * best left and right hand sides; delete the old constraints afterwards
13433  */
13434  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13435  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13436  SCIPdebugPrintCons(scip, cons0, NULL);
13437  SCIPdebugPrintCons(scip, cons1, NULL);
13438 
13439  if( coefsequal )
13440  {
13441  /* the coefficients of both rows are equal */
13442  lhs = MAX(consdata0->lhs, consdata1->lhs);
13443  rhs = MIN(consdata0->rhs, consdata1->rhs);
13444  }
13445  else
13446  {
13447  /* the coefficients of both rows are negations */
13448  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13449  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13450  }
13451  if( SCIPisFeasLT(scip, rhs, lhs) )
13452  {
13453  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13454  *cutoff = TRUE;
13455  break;
13456  }
13457 
13458  /* check which constraint has to stay;
13459  * changes applied to an upgraded constraint will not be considered in the instance */
13460  if( consdata0->upgraded )
13461  {
13462  assert(!consdata1->upgraded);
13463  consstay = cons1;
13464 #ifndef NDEBUG
13465  consdatastay = consdata1;
13466 #endif
13467 
13468  consdel = cons0;
13469  consdatadel = consdata0;
13470  consinddel = chkind;
13471  }
13472  else
13473  {
13474  consstay = cons0;
13475 #ifndef NDEBUG
13476  consdatastay = consdata0;
13477 #endif
13478 
13479  consdel = cons1;
13480  consdatadel = consdata1;
13481  consinddel = c;
13482  }
13483 
13484  /* update the sides of consstay */
13485  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13486  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13487  if( !consdata0->upgraded )
13488  {
13489  assert(consstay == cons0);
13490  cons0lhs = consdata0->lhs;
13491  cons0rhs = consdata0->rhs;
13492  }
13493 
13494  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13495  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13496 
13497  assert( !consdatastay->upgraded );
13498  /* delete consdel */
13499  SCIP_CALL( SCIPdelCons(scip, consdel) );
13500  conss[consinddel] = NULL;
13501  if( !consdatadel->upgraded )
13502  (*ndelconss)++;
13503  continue;
13504  }
13505 
13506  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13507  * redundant
13508  */
13509  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13510  {
13511  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13512  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13513  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13514  SCIPdebugPrintCons(scip, cons0, NULL);
13515  SCIPdebugPrintCons(scip, cons1, NULL);
13516 
13517  /* check for infeasibility */
13518  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13519  {
13520  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13521  *cutoff = TRUE;
13522  break;
13523  }
13524 
13525  /* remove redundant left hand side */
13526  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13527  {
13528  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13529  cons0lhs = consdata0->lhs;
13530  cons0isequality = FALSE;
13531  if( !consdata0->upgraded )
13532  {
13533  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13534  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13535 
13536  (*nchgsides)++;
13537  }
13538  }
13539  }
13540  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13541  {
13542  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13543  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13544  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13545  SCIPdebugPrintCons(scip, cons1, NULL);
13546  SCIPdebugPrintCons(scip, cons0, NULL);
13547 
13548  /* check for infeasibility */
13549  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13550  {
13551  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13552  *cutoff = TRUE;
13553  break;
13554  }
13555 
13556  /* remove redundant left hand side */
13557  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13558  {
13559  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13560  cons1isequality = FALSE;
13561  if( !consdata1->upgraded )
13562  {
13563  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13564  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13565 
13566  (*nchgsides)++;
13567  }
13568  }
13569  }
13570  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13571  {
13572  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13573  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13574  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13575  SCIPdebugPrintCons(scip, cons0, NULL);
13576  SCIPdebugPrintCons(scip, cons1, NULL);
13577 
13578  /* check for infeasibility */
13579  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13580  {
13581  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13582  *cutoff = TRUE;
13583  break;
13584  }
13585 
13586  /* remove redundant right hand side */
13587  if( !SCIPisInfinity(scip, consdata0->rhs) )
13588  {
13589  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13590  cons0rhs = consdata0->rhs;
13591  cons0isequality = FALSE;
13592  if( !consdata0->upgraded )
13593  {
13594  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13595  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13596 
13597  (*nchgsides)++;
13598  }
13599  }
13600  }
13601  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13602  {
13603  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13604  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13605  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13606  SCIPdebugPrintCons(scip, cons1, NULL);
13607  SCIPdebugPrintCons(scip, cons0, NULL);
13608 
13609  /* check for infeasibility */
13610  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13611  {
13612  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13613  *cutoff = TRUE;
13614  break;
13615  }
13616 
13617  /* remove redundant right hand side */
13618  if( !SCIPisInfinity(scip, consdata1->rhs) )
13619  {
13620  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13621  cons1isequality = FALSE;
13622  if( !consdata1->upgraded )
13623  {
13624  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13625  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13626 
13627  (*nchgsides)++;
13628  }
13629  }
13630  }
13631 
13632  /* check for now redundant constraints */
13633  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13634  {
13635  /* consdata0 became redundant */
13636  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13637  SCIP_CALL( SCIPdelCons(scip, cons0) );
13638  conss[chkind] = NULL;
13639  if( !consdata0->upgraded )
13640  {
13641  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13642  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13643 
13644  (*ndelconss)++;
13645  }
13646  continue;
13647  }
13648  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13649  {
13650  /* consdata1 became redundant */
13651  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13652  SCIP_CALL( SCIPdelCons(scip, cons1) );
13653  conss[c] = NULL;
13654  if( !consdata1->upgraded )
13655  {
13656  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13657  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13658 
13659  (*ndelconss)++;
13660  }
13661  continue;
13662  }
13663 
13664  /* check, if we want to aggregate an (in)equality with an equality:
13665  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13666  */
13667  if( tryaggregation )
13668  {
13669  SCIP_Bool aggregated;
13670 
13671  assert(consdata0->nvars == nvarscommon + nvars0minus1);
13672  assert(consdata1->nvars == nvarscommon + nvars1minus0);
13673 
13674  aggregated = FALSE;
13675  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13676  {
13677  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13678  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13679  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13680  nchgcoefs, &aggregated) );
13681 
13682  /* update array of active constraints */
13683  if( aggregated )
13684  {
13685  assert(!SCIPconsIsActive(cons0));
13686  assert(SCIPconsIsActive(cons1));
13687  conss[chkind] = NULL;
13688  }
13689  }
13690  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13691  {
13692  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13693  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13694  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13695  nchgcoefs, &aggregated) );
13696 
13697  /* update array of active constraints */
13698  if( aggregated )
13699  {
13700  assert(!SCIPconsIsActive(cons1));
13701  assert(SCIPconsIsActive(cons0));
13702  conss[c] = NULL;
13703  }
13704  }
13705  }
13706  }
13707 
13708  /* free temporary memory */
13709  SCIPfreeBufferArray(scip, &diffidx1minus0);
13710  SCIPfreeBufferArray(scip, &diffidx0minus1);
13711  SCIPfreeBufferArray(scip, &commonidx1);
13712  SCIPfreeBufferArray(scip, &commonidx0);
13713 
13714  return SCIP_OKAY;
13715 }
13716 
13717 /** do stuffing presolving on a single constraint */
13718 static
13720  SCIP* scip, /**< SCIP data structure */
13721  SCIP_CONS* cons, /**< linear constraint */
13722  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13723  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13724  * constraints using the cheapest variable? */
13725  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13726  int* nfixedvars, /**< pointer to count the total number of fixed variables */
13727  int* nchgbds /**< pointer to count the total number of tightened bounds */
13728  )
13729 {
13730  SCIP_CONSDATA* consdata;
13731  SCIP_Real* ratios;
13732  int* varpos;
13733  SCIP_Bool* swapped;
13734  SCIP_VAR** vars;
13735  SCIP_Real* vals;
13736  SCIP_VAR* var;
13737  SCIP_Real lb;
13738  SCIP_Real ub;
13739  SCIP_Real minactivity;
13740  SCIP_Real maxactivity;
13741  SCIP_Real maxcondactivity;
13742  SCIP_Real mincondactivity;
13743  SCIP_Real rhs;
13744  SCIP_Real val;
13745  SCIP_Real obj;
13746  SCIP_Real factor;
13747  SCIP_Bool minactisrelax;
13748  SCIP_Bool maxactisrelax;
13749  SCIP_Bool tryfixing;
13750  int nsingletons;
13751  int idx;
13752  int v;
13753  int nvars;
13754 
13755  assert(scip != NULL);
13756  assert(cons != NULL);
13757  assert(nfixedvars != NULL);
13758 
13759  consdata = SCIPconsGetData(cons);
13760 
13761  /* we only want to run for inequalities */
13762  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13763  return SCIP_OKAY;
13764 
13765  if( singlevarstuffing )
13766  {
13767  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13768  }
13769  else
13770  {
13771  minactivity = SCIP_INVALID;
13772  maxactivity = SCIP_INVALID;
13773  }
13774 
13775  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13776  * the new maxactivity is minus the old minactivity then
13777  */
13778  if( SCIPisInfinity(scip, consdata->rhs) )
13779  {
13780  SCIP_Real tmp;
13781  rhs = -consdata->lhs;
13782  factor = -1.0;
13783  tmp = maxactivity;
13784  maxactivity = -minactivity;
13785  minactivity = -tmp;
13786  }
13787  else
13788  {
13789  assert(SCIPisInfinity(scip, -consdata->lhs));
13790  rhs = consdata->rhs;
13791  factor = 1.0;
13792  }
13793 
13794  nvars = consdata->nvars;
13795  vars = consdata->vars;
13796  vals = consdata->vals;
13797 
13798  /* check for continuous singletons */
13799  if( singletonstuffing )
13800  {
13801  for( v = 0; v < nvars; ++v )
13802  {
13803  var = vars[v];
13804 
13805  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13807  break;
13808  }
13809  }
13810  else
13811  /* we don't want to go into the next block */
13812  v = nvars;
13813 
13814  /* a singleton was found -> perform singleton variable stuffing */
13815  if( v < nvars )
13816  {
13817  assert(singletonstuffing);
13818 
13819  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
13820  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
13821  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
13822 
13823  tryfixing = TRUE;
13824  nsingletons = 0;
13825  mincondactivity = 0.0;
13826  maxcondactivity = 0.0;
13827 
13828  for( v = 0; v < nvars; ++v )
13829  {
13830  var = vars[v];
13831  lb = SCIPvarGetLbGlobal(var);
13832  ub = SCIPvarGetUbGlobal(var);
13833  obj = SCIPvarGetObj(var);
13834  val = factor * vals[v];
13835 
13836  assert(!SCIPisZero(scip, val));
13837 
13838  /* the variable is a singleton and continuous */
13839  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13841  {
13842  if( SCIPisNegative(scip, obj) && val > 0 )
13843  {
13844  /* case 1: obj < 0 and coef > 0 */
13845  if( SCIPisInfinity(scip, -lb) )
13846  {
13847  tryfixing = FALSE;
13848  break;
13849  }
13850 
13851  maxcondactivity += val * lb;
13852  mincondactivity += val * lb;
13853  swapped[v] = FALSE;
13854  ratios[nsingletons] = obj / val;
13855  varpos[nsingletons] = v;
13856  nsingletons++;
13857  }
13858  else if( SCIPisPositive(scip, obj) && val < 0 )
13859  {
13860  /* case 2: obj > 0 and coef < 0 */
13861  if( SCIPisInfinity(scip, ub) )
13862  {
13863  tryfixing = FALSE;
13864  break;
13865  }
13866  /* multiply column by (-1) to become case 1.
13867  * now bounds are swapped: ub := -lb, lb := -ub
13868  */
13869 
13870  maxcondactivity += val * ub;
13871  mincondactivity += val * ub;
13872  swapped[v] = TRUE;
13873  ratios[nsingletons] = obj / val;
13874  varpos[nsingletons] = v;
13875  nsingletons++;
13876  }
13877  else if( val > 0 )
13878  {
13879  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
13880  * we only consider the lower bound for the constants
13881  */
13882  assert(!SCIPisNegative(scip, obj));
13883 
13884  if( SCIPisInfinity(scip, -lb) )
13885  {
13886  /* maybe unbounded */
13887  tryfixing = FALSE;
13888  break;
13889  }
13890 
13891  maxcondactivity += val * lb;
13892  mincondactivity += val * lb;
13893  }
13894  else
13895  {
13896  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
13897  * we only consider the upper bound for the constants
13898  */
13899  assert(!SCIPisPositive(scip, obj));
13900  assert(val < 0);
13901 
13902  if( SCIPisInfinity(scip, ub) )
13903  {
13904  /* maybe unbounded */
13905  tryfixing = FALSE;
13906  break;
13907  }
13908 
13909  maxcondactivity += val * ub;
13910  mincondactivity += val * ub;
13911  }
13912  }
13913  else
13914  {
13915  /* consider contribution of discrete variables, non-singleton
13916  * continuous variables and variables with more than one lock
13917  */
13918  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13919  {
13920  tryfixing = FALSE;
13921  break;
13922  }
13923 
13924  if( val > 0 )
13925  {
13926  maxcondactivity += val * ub;
13927  mincondactivity += val * lb;
13928  }
13929  else
13930  {
13931  maxcondactivity += val * lb;
13932  mincondactivity += val * ub;
13933  }
13934  }
13935  }
13936  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
13937  {
13938  SCIP_Real delta;
13939  SCIP_Bool tightened;
13940 #ifdef SCIP_DEBUG
13941  int oldnfixedvars = *nfixedvars;
13942  int oldnchgbds = *nchgbds;
13943 #endif
13944 
13945  SCIPsortRealInt(ratios, varpos, nsingletons);
13946 
13947  /* verify which singleton continuous variables can be fixed */
13948  for( v = 0; v < nsingletons; ++v )
13949  {
13950  idx = varpos[v];
13951  var = vars[idx];
13952  val = factor * vals[idx];
13953  lb = SCIPvarGetLbGlobal(var);
13954  ub = SCIPvarGetUbGlobal(var);
13955 
13956  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
13957  assert((val < 0) == swapped[idx]);
13958  val = REALABS(val);
13959 
13960  /* stop fixing if variable bounds are not finite */
13961  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13962  break;
13963 
13964  assert((SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1);
13965  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
13966 
13967  /* calculate the change in the row activities if this variable changes
13968  * its value from its worst to its best bound
13969  */
13970  if( swapped[idx] )
13971  delta = -(lb - ub) * val;
13972  else
13973  delta = (ub - lb) * val;
13974 
13975  assert(!SCIPisNegative(scip, delta));
13976 
13977  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
13978  {
13979  if( swapped[idx] )
13980  {
13981  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
13982  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
13983 
13984  }
13985  else
13986  {
13987  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
13988  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
13989  }
13990 
13991  if( *cutoff )
13992  break;
13993  if( tightened )
13994  {
13995  (*nfixedvars)++;
13996  }
13997  }
13998  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
13999  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14000  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14001  * troubles in case of large bounds.
14002  */
14003  else if( SCIPisLE(scip, rhs, mincondactivity) )
14004  {
14005  if( swapped[idx] )
14006  {
14007  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14008  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14009  }
14010  else
14011  {
14012  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14013  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14014  }
14015 
14016  if( *cutoff )
14017  break;
14018  if( tightened )
14019  {
14020  (*nfixedvars)++;
14021  }
14022  }
14023 
14024  maxcondactivity += delta;
14025  mincondactivity += delta;
14026  }
14027 
14028 #ifdef SCIP_DEBUG
14029  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14030  {
14031  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14032  }
14033 #endif
14034  }
14035 
14036  SCIPfreeBufferArray(scip, &swapped);
14037  SCIPfreeBufferArray(scip, &ratios);
14038  SCIPfreeBufferArray(scip, &varpos);
14039  }
14040 
14041  /* perform single-variable stuffing:
14042  * for a linear inequality
14043  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14044  * with a_i > 0 and objective coefficients c_i < 0,
14045  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14046  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14047  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14048  * is redundant.
14049  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14050  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14051  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14052  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14053  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14054  * upper bound.
14055  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14056  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14057  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14058  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14059  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14060  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14061  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14062  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14063  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14064  * c_k * ceil((maxactivity - rhs)/val) is still better than
14065  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14066  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14067  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14068  * sign of coefficients in constraint and objective prevent the use of this method.
14069  */
14070  if( singlevarstuffing && !SCIPisInfinity(scip, -minactivity) )
14071  {
14072  SCIP_Real bestratio = -SCIPinfinity(scip);
14073  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14074  SCIP_Real ratio;
14075  int bestindex = -1;
14076  int bestuplocks = 0;
14077  int bestdownlocks = 1;
14078  int downlocks;
14079  int uplocks;
14080  int oldnfixedvars;
14081  int oldnchgbds;
14082 
14083  SCIPdebug( oldnfixedvars = *nfixedvars; )
14084  SCIPdebug( oldnchgbds = *nchgbds; )
14085  /* loop over all variables to identify the best and second-best ratio */
14086  for( v = 0; v < nvars; ++v )
14087  {
14088  var = vars[v];
14089  obj = SCIPvarGetObj(var);
14090  val = factor * vals[v];
14091 
14092  assert(!SCIPisZero(scip, val));
14093 
14094  ratio = obj / val;
14095 
14096  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14097  if( !SCIPisNegative(scip, ratio) )
14098  {
14099  bestindex = -1;
14100  break;
14101  }
14102 
14103  if( val > 0 )
14104  {
14105  downlocks = SCIPvarGetNLocksDown(var);
14106  uplocks = SCIPvarGetNLocksUp(var);
14107  }
14108  else
14109  {
14110  downlocks = SCIPvarGetNLocksUp(var);
14111  uplocks = SCIPvarGetNLocksDown(var);
14112  }
14113 
14114  /* better ratio, update best candidate
14115  * @todo use some tolerance
14116  * @todo check size of domain and updated ratio for integer variables already?
14117  */
14118  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14119  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14120  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14121  {
14122  /* best index becomes second-best*/
14123  if( bestindex != -1 )
14124  {
14125  /* second-best index must not have more than 1 uplock */
14126  if( bestuplocks > 1 )
14127  {
14128  bestindex = -1;
14129  break;
14130  }
14131  else
14132  {
14133  secondbestratio = bestratio;
14134  }
14135  }
14136  bestdownlocks = downlocks;
14137  bestuplocks = uplocks;
14138  bestratio = ratio;
14139  bestindex = v;
14140 
14141  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14142  * if it is not the best, it has too many uplocks -> not applicable
14143  */
14144  if( bestdownlocks > 0 && bestuplocks > 1 )
14145  {
14146  bestindex = -1;
14147  break;
14148  }
14149  }
14150  else
14151  {
14152  /* non-best index must not have more than 1 uplock */
14153  if( uplocks > 1 )
14154  {
14155  bestindex = -1;
14156  break;
14157  }
14158  /* update second-best ratio */
14159  if( ratio > secondbestratio )
14160  {
14161  secondbestratio = ratio;
14162  }
14163  }
14164  }
14165 
14166  /* check if we can apply single variable stuffing */
14167  if( bestindex != -1 && bestdownlocks == 0 )
14168  {
14169  SCIP_Bool tightened = FALSE;
14170  SCIP_Real bounddelta;
14171 
14172  var = vars[bestindex];
14173  obj = SCIPvarGetObj(var);
14174  val = factor * vals[bestindex];
14175  lb = SCIPvarGetLbGlobal(var);
14176  ub = SCIPvarGetUbGlobal(var);
14177  tryfixing = TRUE;
14178 
14179  if( val < 0 )
14180  {
14181  assert(!SCIPisNegative(scip, obj));
14182 
14183  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14184  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14185  {
14186  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14187  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14188  assert(SCIPisPositive(scip, activitydelta));
14189 
14190  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14191 
14192  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14193  assert(SCIPisPositive(scip, bounddelta));
14194  }
14195  else
14196  bounddelta = (maxactivity - rhs)/-val;
14197 
14198  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14199 
14200  if( tryfixing )
14201  {
14202  assert(SCIPvarGetNLocksUp(var) == 0);
14203 
14204  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14205  {
14206  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14207  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14208  }
14209  else
14210  {
14211  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14212  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14213  }
14214  }
14215  }
14216  else
14217  {
14218  assert(!SCIPisPositive(scip, obj));
14219 
14220  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14221  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14222  {
14223  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14224  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14225  assert(SCIPisPositive(scip, activitydelta));
14226 
14227  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14228 
14229  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14230  assert(SCIPisPositive(scip, bounddelta));
14231  }
14232  else
14233  bounddelta = (maxactivity - rhs)/val;
14234 
14235  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14236 
14237  if( tryfixing )
14238  {
14239  assert(SCIPvarGetNLocksDown(var) == 0);
14240 
14241  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14242  {
14243  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14244  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14245  }
14246  else
14247  {
14248  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14249  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14250  }
14251  }
14252  }
14253 
14254  if( *cutoff )
14255  return SCIP_OKAY;
14256  if( tightened )
14257  {
14258  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14259  ++(*nfixedvars);
14260  else
14261  ++(*nchgbds);
14262 
14263  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14264  for( v = 0; v < nvars; ++v )
14265  {
14266  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]),
14267  SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]), SCIPvarGetNLocksDown(vars[v]), SCIPvarGetNLocksUp(vars[v]),
14268  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14269  }
14270  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14271 
14272  for( v = 0; v < nvars; ++v )
14273  {
14274  if( v == bestindex )
14275  continue;
14276 
14277  if( factor * vals[v] < 0 )
14278  {
14279  assert(SCIPvarGetNLocksDown(vars[v]) == 1);
14280  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14281  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14282  }
14283  else
14284  {
14285  assert(SCIPvarGetNLocksUp(vars[v]) == 1);
14286  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14287  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14288  }
14289 
14290  if( *cutoff )
14291  return SCIP_OKAY;
14292  if( tightened )
14293  ++(*nfixedvars);
14294  }
14295  SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14296  }
14297  }
14298  }
14299 
14300  return SCIP_OKAY;
14301 }
14302 
14303 /** applies full dual presolving on variables that only appear in linear constraints */
14304 static
14306  SCIP* scip, /**< SCIP data structure */
14307  SCIP_CONS** conss, /**< constraint set */
14308  int nconss, /**< number of constraints */
14309  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14310  int* nchgbds /**< pointer to count the number of bound changes */
14311  )
14312 {
14313  SCIP_Real* redlb;
14314  SCIP_Real* redub;
14315  int* nlocksdown;
14316  int* nlocksup;
14317  SCIP_Bool* isimplint;
14318  SCIP_VAR** origvars;
14319  SCIP_VAR** vars;
14320  SCIP_VAR** conscontvars;
14321  int nvars;
14322  int nbinvars;
14323  int nintvars;
14324  int ncontvars;
14325  int v;
14326  int c;
14327 
14328  /* we calculate redundancy bounds with the following meaning:
14329  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14330  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14331  * then:
14332  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14333  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14334  */
14335 
14336  /* Additionally, we detect continuous variables that are implicitly integral.
14337  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14338  * and all constraints (including the bounds as trivial constraints) in which:
14339  * c_j > 0: the variable is down-locked,
14340  * c_j < 0: the variable is up-locked,
14341  * c_j = 0: the variable appears
14342  * have, apart from j, only integer variables with integral coefficients and integral sides.
14343  * This is because then, the value of the variable is either determined by one of its bounds or
14344  * by one of these constraints, and in all cases, the value of the variable is integral.
14345  */
14346 
14347  assert(scip != NULL);
14348  assert(nconss == 0 || conss != NULL);
14349  assert(nchgbds != NULL);
14350  assert(!SCIPinProbing(scip));
14351 
14352  /* get active variables */
14353  nvars = SCIPgetNVars(scip);
14354  origvars = SCIPgetVars(scip);
14355 
14356  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14357  nbinvars = SCIPgetNBinVars(scip);
14358  if( nbinvars == nvars )
14359  return SCIP_OKAY;
14360 
14361  /* get number of continuous variables */
14362  ncontvars = SCIPgetNContVars(scip);
14363  nintvars = nvars - ncontvars;
14364 
14365  /* copy the variable array since this array might change during the curse of this algorithm */
14366  nvars = nvars - nbinvars;
14367  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14368 
14369  /* allocate temporary memory */
14370  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14371  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14372  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14373  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14374  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14375  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14376 
14377  /* initialize redundancy bounds */
14378  for( v = 0; v < nvars; ++v )
14379  {
14380  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14381  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14382  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14383  }
14384  BMSclearMemoryArray(nlocksdown, nvars);
14385  BMSclearMemoryArray(nlocksup, nvars);
14386 
14387  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14388  * We better not use SCIPisFeasIntegral() in these checks.
14389  */
14390  for( v = 0; v < ncontvars; v++ )
14391  {
14392  SCIP_VAR* var;
14393  SCIP_Real obj;
14394  SCIP_Real lb;
14395  SCIP_Real ub;
14396 
14397  var = vars[v + nintvars - nbinvars];
14398  lb = SCIPvarGetLbGlobal(var);
14399  ub = SCIPvarGetUbGlobal(var);
14400 
14401  obj = SCIPvarGetObj(var);
14402  if( SCIPisZero(scip, obj) )
14403  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14404  else
14405  {
14406  if( SCIPisPositive(scip, obj) )
14407  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14408  else
14409  {
14410  assert(SCIPisNegative(scip, obj));
14411  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14412  }
14413  }
14414  }
14415 
14416  /* scan all constraints */
14417  for( c = 0; c < nconss; ++c )
14418  {
14419  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14420  * part of checked disjunctions)
14421  */
14422  if( SCIPconsIsLocked(conss[c]) )
14423  {
14424  SCIP_CONSDATA* consdata;
14425  SCIP_Bool lhsexists;
14426  SCIP_Bool rhsexists;
14427  SCIP_Bool hasimpliedpotential;
14428  SCIP_Bool integralcoefs;
14429  int nlockspos;
14430  int contvarpos;
14431  int nconscontvars;
14432  int i;
14433 
14434  consdata = SCIPconsGetData(conss[c]);
14435  assert(consdata != NULL);
14436 
14437  /* get number of times the constraint was locked */
14438  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14439 
14440  /* we do not want to include constraints with locked negation (this would be too weird) */
14441  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14442  {
14443  /* mark all continuous variables as not being implicit integral */
14444  for( i = 0; i < consdata->nvars; ++i )
14445  {
14446  SCIP_VAR* var;
14447 
14448  var = consdata->vars[i];
14450  {
14451  int contv;
14452  contv = SCIPvarGetProbindex(var) - nintvars;
14453  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14454  isimplint[contv] = FALSE;
14455  }
14456  }
14457  continue;
14458  }
14459 
14460  /* check for existing sides */
14461  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14462  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14463 
14464  /* count locks and update redundancy bounds */
14465  contvarpos = -1;
14466  nconscontvars = 0;
14467  hasimpliedpotential = FALSE;
14468  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14469 
14470  for( i = 0; i < consdata->nvars; ++i )
14471  {
14472  SCIP_VAR* var;
14473  SCIP_Real val;
14474  SCIP_Real minresactivity;
14475  SCIP_Real maxresactivity;
14476  SCIP_Real newredlb;
14477  SCIP_Real newredub;
14478  SCIP_Bool minisrelax;
14479  SCIP_Bool maxisrelax;
14480  SCIP_Bool isminsettoinfinity;
14481  SCIP_Bool ismaxsettoinfinity;
14482  int arrayindex;
14483 
14484  var = consdata->vars[i];
14485  val = consdata->vals[i];
14486 
14487  /* check if still all integer variables have integral coefficients */
14488  if( SCIPvarIsIntegral(var) )
14489  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14490 
14491  /* we do not need to process binary variables */
14492  if( SCIPvarIsBinary(var) )
14493  continue;
14494 
14495  if( SCIPconsIsModifiable(conss[c]) )
14496  {
14497  minresactivity = -SCIPinfinity(scip);
14498  maxresactivity = SCIPinfinity(scip);
14499  isminsettoinfinity = TRUE;
14500  ismaxsettoinfinity = TRUE;
14501  }
14502  else
14503  {
14504  /* calculate residual activity bounds if variable would be fixed to zero */
14505  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14506  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14507 
14508  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14509  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14510  * This is needed, because we do not want to rely on relaxed finite resactivities.
14511  */
14512  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14513 
14514  /* check minresactivity for reliability */
14515  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14516  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14517 
14518  /* check maxresactivity for reliability */
14519  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14520  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14521  }
14522 
14523  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14524 
14525  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14526 
14527  newredlb = redlb[arrayindex];
14528  newredub = redub[arrayindex];
14529  if( val > 0.0 )
14530  {
14531  if( lhsexists )
14532  {
14533  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14534  nlocksdown[arrayindex] += nlockspos;
14535  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14536  }
14537  if( rhsexists )
14538  {
14539  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14540  nlocksup[arrayindex] += nlockspos;
14541  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14542  }
14543  }
14544  else
14545  {
14546  if( lhsexists )
14547  {
14548  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14549  nlocksup[arrayindex] += nlockspos;
14550  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14551  }
14552  if( rhsexists )
14553  {
14554  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14555  nlocksdown[arrayindex] += nlockspos;
14556  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14557  }
14558  }
14559 
14560  /* if the variable is integer, we have to round the value to the next integral value */
14561  if( SCIPvarIsIntegral(var) )
14562  {
14563  if( !SCIPisInfinity(scip, newredlb) )
14564  newredlb = SCIPceil(scip, newredlb);
14565  if( !SCIPisInfinity(scip, -newredub) )
14566  newredub = SCIPfloor(scip, newredub);
14567  }
14568 
14569  /* update redundancy bounds */
14570  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14571  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14572 
14573  /* collect the continuous variables of the constraint */
14575  {
14576  int contv;
14577 
14578  assert(nconscontvars < ncontvars);
14579  contvarpos = i;
14580  conscontvars[nconscontvars] = var;
14581  nconscontvars++;
14582 
14583  contv = SCIPvarGetProbindex(var) - nintvars;
14584  assert(0 <= contv && contv < ncontvars);
14585  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14586  }
14587  }
14588 
14589  /* update implied integer status of continuous variables */
14590  if( hasimpliedpotential )
14591  {
14592  if( nconscontvars > 1 || !integralcoefs )
14593  {
14594  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14595  * none of the continuous variables is implied integer
14596  */
14597  for( i = 0; i < nconscontvars; i++ )
14598  {
14599  int contv;
14600  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14601  assert(0 <= contv && contv < ncontvars);
14602  isimplint[contv] = FALSE;
14603  }
14604  }
14605  else
14606  {
14607  SCIP_VAR* var;
14608  SCIP_Real val;
14609  SCIP_Real absval;
14610  int contv;
14611 
14612  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14613  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14614  * side(s) of the constraint is integral
14615  */
14616  assert(nconscontvars == 1);
14617  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14618  var = consdata->vars[contvarpos];
14619  val = consdata->vals[contvarpos];
14620  contv = SCIPvarGetProbindex(var) - nintvars;
14621  assert(0 <= contv && contv < ncontvars);
14622  assert(isimplint[contv]);
14623 
14624  absval = REALABS(val);
14625  if( !SCIPisEQ(scip, absval, 1.0) )
14626  isimplint[contv] = FALSE;
14627  else
14628  {
14629  SCIP_Real obj;
14630 
14631  obj = SCIPvarGetObj(var);
14632  if( obj * val >= 0.0 && lhsexists )
14633  {
14634  /* the variable may be blocked by the constraint's left hand side */
14635  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14636  }
14637  if( obj * val <= 0.0 && rhsexists )
14638  {
14639  /* the variable may be blocked by the constraint's left hand side */
14640  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14641  }
14642  }
14643  }
14644  }
14645  }
14646  }
14647 
14648  /* check if any bounds can be tightened due to optimality */
14649  for( v = 0; v < nvars; ++v )
14650  {
14651  SCIP_VAR* var;
14652  SCIP_Real obj;
14653  SCIP_Bool infeasible;
14654  SCIP_Bool tightened;
14655 
14656  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14657  assert(SCIPvarGetNLocksDown(vars[v]) >= nlocksdown[v]);
14658  assert(SCIPvarGetNLocksUp(vars[v]) >= nlocksup[v]);
14659 
14660  var = vars[v];
14661  obj = SCIPvarGetObj(var);
14662  if( obj >= 0.0 )
14663  {
14664  /* making the variable as small as possible does not increase the objective:
14665  * check if all down locks of the variables are due to linear constraints;
14666  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14667  */
14668  if( SCIPvarGetNLocksDown(var) == nlocksdown[v]
14669  && !SCIPisInfinity(scip, -redlb[v])
14670  && redlb[v] < SCIPvarGetUbGlobal(var) )
14671  {
14672  SCIP_Real ub;
14673 
14674  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14675  * -> tighten upper bound to x_v <= redlb[v]
14676  */
14677  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14679  redlb[v]);
14680  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14681  assert(!infeasible);
14682 
14683  ub = SCIPvarGetUbGlobal(var);
14684  redub[v] = MIN(redub[v], ub);
14685  if( tightened )
14686  (*nchgbds)++;
14687  }
14688  }
14689  if( obj <= 0.0 )
14690  {
14691  /* making the variable as large as possible does not increase the objective:
14692  * check if all up locks of the variables are due to linear constraints;
14693  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14694  */
14695  if( SCIPvarGetNLocksUp(var) == nlocksup[v]
14696  && !SCIPisInfinity(scip, redub[v])
14697  && redub[v] > SCIPvarGetLbGlobal(var) )
14698  {
14699  SCIP_Real lb;
14700 
14701  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14702  * -> tighten lower bound to x_v >= redub[v]
14703  */
14704  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14706  redub[v]);
14707  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14708  assert(!infeasible);
14709 
14710  lb = SCIPvarGetLbGlobal(var);
14711  redlb[v] = MAX(redlb[v], lb);
14712  if( tightened )
14713  (*nchgbds)++;
14714  }
14715  }
14716  }
14717 
14718  /* upgrade continuous variables to implied integers */
14719  for( v = nintvars - nbinvars; v < nvars; ++v )
14720  {
14721  SCIP_VAR* var;
14722  SCIP_Bool infeasible;
14723 
14724  var = vars[v];
14725  assert(var != NULL);
14726 
14727  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14728  assert(SCIPvarGetNLocksDown(var) >= nlocksdown[v]);
14729  assert(SCIPvarGetNLocksUp(var) >= nlocksup[v]);
14730  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14731 
14732  /* we can only conclude implied integrality if the variable appears in no other constraint */
14733  if( isimplint[v - nintvars + nbinvars]
14734  && SCIPvarGetNLocksDown(var) == nlocksdown[v]
14735  && SCIPvarGetNLocksUp(var) == nlocksup[v] )
14736  {
14737 
14738  /* since we locally copied the variable array we can change the variable type immediately */
14739  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
14740 
14741  if( infeasible )
14742  {
14743  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14744  *cutoff = TRUE;
14745 
14746  break;
14747  }
14748 
14749  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
14751  }
14752  }
14753 
14754  /* free temporary memory */
14755  SCIPfreeBufferArray(scip, &conscontvars);
14756  SCIPfreeBufferArray(scip, &isimplint);
14757  SCIPfreeBufferArray(scip, &nlocksup);
14758  SCIPfreeBufferArray(scip, &nlocksdown);
14759  SCIPfreeBufferArray(scip, &redub);
14760  SCIPfreeBufferArray(scip, &redlb);
14761 
14762  SCIPfreeBufferArray(scip, &vars);
14763 
14764  return SCIP_OKAY;
14765 }
14766 
14767 /** helper function to enforce constraints */
14768 static
14770  SCIP* scip, /**< SCIP data structure */
14771  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14772  SCIP_CONS** conss, /**< constraints to process */
14773  int nconss, /**< number of constraints */
14774  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14775  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14776  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14777  )
14778 {
14779  SCIP_CONSHDLRDATA* conshdlrdata;
14780  SCIP_Bool checkrelmaxabs;
14781  SCIP_Bool violated;
14782  SCIP_Bool cutoff = FALSE;
14783  int c;
14784 
14785  assert(scip != NULL);
14786  assert(conshdlr != NULL);
14787  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14788  assert(result != NULL);
14789 
14790  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14791  assert(conshdlrdata != NULL);
14792 
14793  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14794 
14795  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14796 
14797  /* check for violated constraints
14798  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14799  */
14800  *result = SCIP_FEASIBLE;
14801 
14802  /* check all useful linear constraints for feasibility */
14803  for( c = 0; c < nusefulconss; ++c )
14804  {
14805  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14806 
14807  if( violated )
14808  {
14809  /* insert LP row as cut */
14810  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14811  if ( cutoff )
14812  *result = SCIP_CUTOFF;
14813  else
14814  *result = SCIP_SEPARATED;
14815  }
14816  }
14817 
14818  /* check all obsolete linear constraints for feasibility */
14819  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14820  {
14821  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14822 
14823  if( violated )
14824  {
14825  /* insert LP row as cut */
14826  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14827  if ( cutoff )
14828  *result = SCIP_CUTOFF;
14829  else
14830  *result = SCIP_SEPARATED;
14831  }
14832  }
14833 
14834  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
14835 
14836  return SCIP_OKAY;
14837 }
14838 
14839 /*
14840  * Callback methods of constraint handler
14841  */
14842 
14843 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
14844 static
14845 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
14846 { /*lint --e{715}*/
14847  assert(scip != NULL);
14848  assert(conshdlr != NULL);
14849  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14850 
14851  /* call inclusion method of constraint handler */
14853 
14854  *valid = TRUE;
14855 
14856  return SCIP_OKAY;
14857 }
14858 
14859 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
14860 static
14861 SCIP_DECL_CONSFREE(consFreeLinear)
14862 { /*lint --e{715}*/
14863  SCIP_CONSHDLRDATA* conshdlrdata;
14864 
14865  assert(scip != NULL);
14866  assert(conshdlr != NULL);
14867  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14868 
14869  /* free constraint handler data */
14870  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14871  assert(conshdlrdata != NULL);
14872 
14873  conshdlrdataFree(scip, &conshdlrdata);
14874 
14875  SCIPconshdlrSetData(conshdlr, NULL);
14876 
14877  return SCIP_OKAY;
14879 
14880 
14881 /** initialization method of constraint handler (called after problem was transformed) */
14882 static
14883 SCIP_DECL_CONSINIT(consInitLinear)
14884 {
14885  SCIP_CONSHDLRDATA* conshdlrdata;
14886  int c;
14887 
14888  assert(scip != NULL);
14889 
14890  /* check for event handler */
14891  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14892  assert(conshdlrdata != NULL);
14893  assert(conshdlrdata->eventhdlr != NULL);
14894  assert(nconss == 0 || conss != NULL);
14895 
14896  /* catch events for the constraints */
14897  for( c = 0; c < nconss; ++c )
14898  {
14899  /* catch all events */
14900  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14901  }
14902 
14903  return SCIP_OKAY;
14904 }
14905 
14906 
14907 /** deinitialization method of constraint handler (called before transformed problem is freed) */
14908 static
14909 SCIP_DECL_CONSEXIT(consExitLinear)
14910 {
14911  SCIP_CONSHDLRDATA* conshdlrdata;
14912  int c;
14913 
14914  assert(scip != NULL);
14915 
14916  /* check for event handler */
14917  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14918  assert(conshdlrdata != NULL);
14919  assert(conshdlrdata->eventhdlr != NULL);
14920 
14921  /* drop events for the constraints */
14922  for( c = nconss - 1; c >= 0; --c )
14923  {
14924  SCIP_CONSDATA* consdata;
14925 
14926  consdata = SCIPconsGetData(conss[c]);
14927  assert(consdata != NULL);
14928 
14929  if( consdata->eventdata != NULL )
14930  {
14931  /* drop all events */
14932  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14933  assert(consdata->eventdata == NULL);
14934  }
14935  }
14936 
14937  return SCIP_OKAY;
14938 
14939 }
14940 
14941 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14942 static
14944  SCIP* scip, /**< SCIP data structure */
14945  SCIP_Real lhs, /**< left hand side */
14946  SCIP_Real rhs /**< right hand side */
14947  )
14948 {
14949  assert(scip != NULL);
14950 
14951  return !(SCIPisEQ(scip, lhs, rhs)
14952  || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
14953 }
14954 
14955 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14956 static
14958  SCIP* scip, /**< SCIP data structure */
14959  SCIP_Real x /**< value */
14960  )
14961 {
14962  assert(scip != NULL);
14963 
14964  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
14965 }
14966 
14967 /** performs linear constraint type classification as used for MIPLIB
14968  *
14969  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
14970  *
14971  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
14972  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
14973  * Similarly, if specialized constraints were created through the API, these are currently not present.
14974  */
14976  SCIP* scip, /**< SCIP data structure */
14977  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
14978  )
14979 {
14980  int c;
14981  SCIP_CONSHDLR* conshdlr;
14982  SCIP_CONS** conss;
14983  int nconss;
14984 
14985  assert(scip != NULL);
14986  assert(linconsstats != NULL);
14987  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14988  assert(conshdlr != NULL);
14989 
14990  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
14991  {
14992  conss = SCIPgetConss(scip);
14993  nconss = SCIPgetNConss(scip);
14994  }
14995  else
14996  {
14997  conss = SCIPconshdlrGetConss(conshdlr);
14998  nconss = SCIPconshdlrGetNConss(conshdlr);
14999  }
15000 
15001 
15002  /* reset linear constraint type classification */
15003  SCIPlinConsStatsReset(linconsstats);
15004 
15005  /* loop through all constraints */
15006  for( c = 0; c < nconss; c++ )
15007  {
15008  SCIP_CONS* cons;
15009  SCIP_CONSDATA* consdata;
15010  SCIP_Real lhs;
15011  SCIP_Real rhs;
15012  int i;
15013 
15014  /* get constraint */
15015  cons = conss[c];
15016  assert(cons != NULL);
15017 
15018  /* skip constraints that are not handled by the constraint handler */
15019  if( SCIPconsGetHdlr(cons) != conshdlr )
15020  continue;
15021 
15022  /* get constraint data */
15023  consdata = SCIPconsGetData(cons);
15024  assert(consdata != NULL);
15025  rhs = consdata->rhs;
15026  lhs = consdata->lhs;
15027 
15028  /* merge multiples and delete variables with zero coefficient */
15029  SCIP_CALL( mergeMultiples(scip, cons) );
15030  for( i = 0; i < consdata->nvars; i++ )
15031  {
15032  assert(!SCIPisZero(scip, consdata->vals[i]));
15033  }
15034 
15035  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15036  if( consdata->nvars == 0 )
15037  {
15038  SCIPdebugMsg(scip, "classified as EMPTY: ");
15039  SCIPdebugPrintCons(scip, cons, NULL);
15041 
15042  continue;
15043  }
15044 
15045  /* is constraint of type SCIP_CONSTYPE_FREE? */
15046  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15047  {
15048  SCIPdebugMsg(scip, "classified as FREE: ");
15049  SCIPdebugPrintCons(scip, cons, NULL);
15051 
15052  continue;
15053  }
15054 
15055  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15056  if( consdata->nvars == 1 )
15057  {
15058  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15059  SCIPdebugPrintCons(scip, cons, NULL);
15060  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15061 
15062  continue;
15063  }
15064 
15065  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15066  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15067  {
15068  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15069  SCIPdebugPrintCons(scip, cons, NULL);
15071 
15072  continue;
15073  }
15074 
15075  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15076  if( consdata->nvars == 2 )
15077  {
15078  SCIP_LINCONSTYPE constype;
15079 
15080  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15081  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15082  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15083  {
15084  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15085  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15086  }
15087  else
15088  {
15089  constype = SCIP_LINCONSTYPE_VARBOUND;
15090  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15091  }
15092  SCIPdebugPrintCons(scip, cons, NULL);
15093 
15094  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15095 
15096  continue;
15097  }
15098 
15099  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15100  {
15101  SCIP_Real scale;
15102  SCIP_Real b;
15103  SCIP_Bool unmatched;
15104  int nnegbinvars;
15105 
15106  unmatched = FALSE;
15107  nnegbinvars = 0;
15108 
15109  scale = REALABS(consdata->vals[0]);
15110 
15111  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15112  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15113  {
15114  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15115  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15116  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15117  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15118 
15119  if( consdata->vals[i] < 0.0 )
15120  nnegbinvars++;
15121  }
15122 
15123  if( !unmatched )
15124  {
15125  if( SCIPisEQ(scip, lhs, rhs) )
15126  {
15127  b = rhs/scale + nnegbinvars;
15128  if( SCIPisEQ(scip, 1.0, b) )
15129  {
15130  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15131  SCIPdebugPrintCons(scip, cons, NULL);
15133 
15134  continue;
15135  }
15136  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15137  {
15138  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15139  SCIPdebugPrintCons(scip, cons, NULL);
15141 
15142  continue;
15143  }
15144  }
15145 
15146  /* compute right hand side divided by scale */
15147  if( !SCIPisInfinity(scip, rhs) )
15148  b = rhs/scale + nnegbinvars;
15149  else
15150  b = SCIPinfinity(scip);
15151 
15152  if( SCIPisEQ(scip, 1.0, b) )
15153  {
15154  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15155  SCIPdebugPrintCons(scip, cons, NULL);
15157 
15158  /* relax right hand side to prevent further classifications */
15159  rhs = SCIPinfinity(scip);
15160  }
15161  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15162  {
15163  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15164  SCIPdebugPrintCons(scip, cons, NULL);
15165 
15167 
15168  /* relax right hand side to prevent further classifications */
15169  rhs = SCIPinfinity(scip);
15170  }
15171 
15172  if( !SCIPisInfinity(scip, lhs) )
15173  b = lhs/scale + nnegbinvars;
15174  else
15175  b = SCIPinfinity(scip);
15176 
15177  if( SCIPisEQ(scip, 1.0, b) )
15178  {
15179  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15180  SCIPdebugPrintCons(scip, cons, NULL);
15182 
15183  /* relax left hand side to prevent further classifications */
15184  lhs = -SCIPinfinity(scip);
15185  }
15186 
15187  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15188  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15189  continue;
15190  }
15191  }
15192 
15193  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15194  /* @todo If coefficients or rhs are not integral, we currently do not check
15195  * if the constraint could be scaled (finitely), such that they are.
15196  */
15197  {
15198  SCIP_Real b;
15199  SCIP_Bool unmatched;
15200 
15201  b = rhs;
15202  unmatched = FALSE;
15203  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15204  {
15205  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15206  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15207  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15208  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15209 
15210  if( SCIPisNegative(scip, consdata->vals[i]) )
15211  b -= consdata->vals[i];
15212  }
15213  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15214 
15215  if( !unmatched )
15216  {
15217  if( SCIPisEQ(scip, lhs, rhs) )
15218  {
15219  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15220  SCIPdebugPrintCons(scip, cons, NULL);
15221 
15223 
15224  continue;
15225  }
15226  else
15227  {
15228  SCIP_Bool matched;
15229 
15230  matched = FALSE;
15231  for( i = 0; i < consdata->nvars && !matched; i++ )
15232  {
15233  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15234  }
15235 
15236  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15237  SCIPdebugPrintCons(scip, cons, NULL);
15239  }
15240 
15241  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15242  if( SCIPisInfinity(scip, -lhs) )
15243  continue;
15244  else
15245  rhs = SCIPinfinity(scip);
15246  }
15247  }
15248 
15249  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15250  {
15251  SCIP_Real b;
15252  SCIP_Bool unmatched;
15253 
15254  unmatched = FALSE;
15255 
15256  b = rhs;
15257  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15258 
15259  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15260  {
15261  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15262  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15263  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15264  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15265  }
15266 
15267  if( !unmatched )
15268  {
15269  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15270  SCIPdebugPrintCons(scip, cons, NULL);
15272 
15273  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15274  if( SCIPisInfinity(scip, -lhs) )
15275  continue;
15276  else
15277  rhs = SCIPinfinity(scip);
15278  }
15279  }
15280 
15281  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15282  {
15283  SCIP_Bool unmatched;
15284 
15285  unmatched = FALSE;
15286  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15287  {
15288  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15289  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15290  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15291  unmatched = TRUE;
15292  }
15293 
15294  if( !unmatched )
15295  {
15296  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15297  SCIPdebugPrintCons(scip, cons, NULL);
15298  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15299 
15300  continue;
15301  }
15302  }
15303 
15304  /* no special structure detected */
15305  SCIPdebugMsg(scip, "classified as GENERAL: ");
15306  SCIPdebugPrintCons(scip, cons, NULL);
15307  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15308  }
15309 
15310  return SCIP_OKAY;
15311 }
15312 
15313 
15314 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15315 static
15316 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15317 { /*lint --e{715}*/
15318  int c;
15319 #ifdef SCIP_STATISTIC
15320  SCIP_CONSHDLRDATA* conshdlrdata;
15321  int ngoodconss;
15322  int nallconss;
15323 #endif
15324 
15325  /* delete all linear constraints that were upgraded to a more specific constraint type;
15326  * make sure, only active variables remain in the remaining constraints
15327  */
15328  assert(scip != NULL);
15329 
15330 #ifdef SCIP_STATISTIC
15331  /* count number of well behaved linear constraints */
15332  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15333  assert(conshdlrdata != NULL);
15334 
15335  ngoodconss = 0;
15336  nallconss = 0;
15337 
15338  for( c = 0; c < nconss; ++c )
15339  {
15340  SCIP_CONSDATA* consdata;
15341 
15342  if( SCIPconsIsDeleted(conss[c]) )
15343  continue;
15344 
15345  consdata = SCIPconsGetData(conss[c]);
15346  assert(consdata != NULL);
15347 
15348  if( consdata->upgraded )
15349  continue;
15350 
15351  nallconss++;
15352 
15353  consdataRecomputeMaxActivityDelta(scip, consdata);
15354 
15355  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15356  ngoodconss++;
15357  }
15358  if( nallconss )
15359  {
15360  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15361  }
15362 #endif
15363 
15364  for( c = 0; c < nconss; ++c )
15365  {
15366  SCIP_CONSDATA* consdata;
15367 
15368  if( SCIPconsIsDeleted(conss[c]) )
15369  continue;
15370 
15371  consdata = SCIPconsGetData(conss[c]);
15372  assert(consdata != NULL);
15373 
15374  if( consdata->upgraded )
15375  {
15376  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15377  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15378  */
15379  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15380  }
15381  else
15382  {
15383  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15384  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15385  }
15386  }
15387 
15388  return SCIP_OKAY;
15389 }
15390 
15391 
15392 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15393 static
15394 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15395 { /*lint --e{715}*/
15396  int c;
15397 
15398  assert(scip != NULL);
15399 
15400  /* release the rows of all constraints */
15401  for( c = 0; c < nconss; ++c )
15402  {
15403  SCIP_CONSDATA* consdata;
15404 
15405  consdata = SCIPconsGetData(conss[c]);
15406  assert(consdata != NULL);
15407 
15408  if( consdata->row != NULL )
15409  {
15410  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15411  }
15412  }
15413 
15414  /* if this is a restart, convert cutpool rows into linear constraints */
15415  if( restart )
15416  {
15417  int ncutsadded;
15418 
15419  ncutsadded = 0;
15420 
15421  /* create out of all active cuts in cutpool linear constraints */
15422  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15423 
15424  if( ncutsadded > 0 )
15425  {
15427  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15428  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15429  * line correctly
15430  */
15431  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "\n");
15432  }
15433  }
15434 
15435  return SCIP_OKAY;
15436 }
15437 
15438 
15439 /** constraint deactivation notification method of constraint handler */
15440 static
15441 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15442 { /*lint --e{715}*/
15443 
15444  if( SCIPconsIsDeleted(cons) )
15445  {
15446  SCIP_CONSHDLRDATA* conshdlrdata;
15447  SCIP_CONSDATA* consdata;
15448 
15449  assert(scip != NULL);
15450  assert(conshdlr != NULL);
15451  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15452 
15453  /* get constraint data */
15454  consdata = SCIPconsGetData(cons);
15455  assert(consdata != NULL);
15456 
15457  /* check for event handler */
15458  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15459  assert(conshdlrdata != NULL);
15460  assert(conshdlrdata->eventhdlr != NULL);
15461 
15462  /* free event data */
15463  if( consdata->eventdata != NULL )
15464  {
15465  /* drop bound change events of variables */
15466  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15467  }
15468  assert(consdata->eventdata == NULL);
15469  }
15470 
15471  return SCIP_OKAY;
15472 }
15473 
15474 
15475 /** frees specific constraint data */
15476 static
15477 SCIP_DECL_CONSDELETE(consDeleteLinear)
15478 { /*lint --e{715}*/
15479  assert(scip != NULL);
15480  assert(conshdlr != NULL);
15481  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15482 
15483  if( (*consdata)->eventdata != NULL )
15484  {
15485  SCIP_CONSHDLRDATA* conshdlrdata;
15486 
15487  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15488  assert(conshdlrdata != NULL);
15489 
15490  /* drop all events */
15491  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15492  assert((*consdata)->eventdata == NULL);
15493  }
15495  /* free linear constraint */
15496  SCIP_CALL( consdataFree(scip, consdata) );
15497 
15498  return SCIP_OKAY;
15499 }
15500 
15501 
15502 /** transforms constraint data into data belonging to the transformed problem */
15503 static
15504 SCIP_DECL_CONSTRANS(consTransLinear)
15505 { /*lint --e{715}*/
15506  SCIP_CONSDATA* sourcedata;
15507  SCIP_CONSDATA* targetdata;
15508 
15509  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15510 
15511  assert(scip != NULL);
15512  assert(conshdlr != NULL);
15513  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15514  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15515  assert(sourcecons != NULL);
15516  assert(targetcons != NULL);
15517 
15518  sourcedata = SCIPconsGetData(sourcecons);
15519  assert(sourcedata != NULL);
15520  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15522  /* create linear constraint data for target constraint */
15523  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15524 
15525  /* create target constraint */
15526  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15527  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15528  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15529  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15530  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15531 
15532  return SCIP_OKAY;
15533 }
15534 
15535 
15536 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15537 static
15538 SCIP_DECL_CONSINITLP(consInitlpLinear)
15539 { /*lint --e{715}*/
15540  int c;
15541 
15542  assert(scip != NULL);
15543  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15544 
15545  *infeasible = FALSE;
15546 
15547  for( c = 0; c < nconss && !(*infeasible); ++c )
15548  {
15549  assert(SCIPconsIsInitial(conss[c]));
15550  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15551  }
15552 
15553  return SCIP_OKAY;
15554 }
15556 
15557 /** separation method of constraint handler for LP solutions */
15558 static
15559 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15560 { /*lint --e{715}*/
15561  SCIP_CONSHDLRDATA* conshdlrdata;
15562  SCIP_Real loclowerbound;
15563  SCIP_Real glblowerbound;
15564  SCIP_Real cutoffbound;
15565  SCIP_Real maxbound;
15566  SCIP_Bool separatecards;
15567  SCIP_Bool cutoff;
15568  int c;
15569  int depth;
15570  int nrounds;
15571  int maxsepacuts;
15572  int ncuts;
15573 
15574  assert(scip != NULL);
15575  assert(conshdlr != NULL);
15576  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15577  assert(result != NULL);
15578 
15579  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15580  assert(conshdlrdata != NULL);
15581  depth = SCIPgetDepth(scip);
15582  nrounds = SCIPgetNSepaRounds(scip);
15583 
15584  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15585 
15586  *result = SCIP_DIDNOTRUN;
15587 
15588  /* only call the separator a given number of times at each node */
15589  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15590  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15591  return SCIP_OKAY;
15592 
15593  /* get the maximal number of cuts allowed in a separation round */
15594  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15595 
15596  /* check if we want to produce knapsack cardinality cuts at this node */
15597  loclowerbound = SCIPgetLocalLowerbound(scip);
15598  glblowerbound = SCIPgetLowerbound(scip);
15599  cutoffbound = SCIPgetCutoffbound(scip);
15600  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15601  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15602  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15603 
15604  *result = SCIP_DIDNOTFIND;
15605  ncuts = 0;
15606  cutoff = FALSE;
15607 
15608  /* check all useful linear constraints for feasibility */
15609  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15610  {
15611  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15612  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15613  }
15614 
15615  /* adjust return value */
15616  if( cutoff )
15617  *result = SCIP_CUTOFF;
15618  else if( ncuts > 0 )
15619  *result = SCIP_SEPARATED;
15620 
15621  /* combine linear constraints to get more cuts */
15622  /**@todo further cuts of linear constraints */
15623 
15624  return SCIP_OKAY;
15625 }
15626 
15627 
15628 /** separation method of constraint handler for arbitrary primal solutions */
15629 static
15630 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15631 { /*lint --e{715}*/
15632  SCIP_CONSHDLRDATA* conshdlrdata;
15633  int c;
15634  int depth;
15635  int nrounds;
15636  int maxsepacuts;
15637  int ncuts;
15638  SCIP_Bool cutoff;
15639 
15640  assert(scip != NULL);
15641  assert(conshdlr != NULL);
15642  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15643  assert(result != NULL);
15644 
15645  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15646  assert(conshdlrdata != NULL);
15647  depth = SCIPgetDepth(scip);
15648  nrounds = SCIPgetNSepaRounds(scip);
15649 
15650  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15651 
15652  *result = SCIP_DIDNOTRUN;
15653 
15654  /* only call the separator a given number of times at each node */
15655  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15656  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15657  return SCIP_OKAY;
15658 
15659  /* get the maximal number of cuts allowed in a separation round */
15660  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15661 
15662  *result = SCIP_DIDNOTFIND;
15663  ncuts = 0;
15664  cutoff = FALSE;
15665 
15666  /* check all useful linear constraints for feasibility */
15667  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15668  {
15669  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15670  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15671  }
15672 
15673  /* adjust return value */
15674  if( cutoff )
15675  *result = SCIP_CUTOFF;
15676  else if( ncuts > 0 )
15677  *result = SCIP_SEPARATED;
15678 
15679  /* combine linear constraints to get more cuts */
15680  /**@todo further cuts of linear constraints */
15681 
15682  return SCIP_OKAY;
15683 }
15684 
15685 
15686 /** constraint enforcing method of constraint handler for LP solutions */
15687 static
15688 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15689 { /*lint --e{715}*/
15690  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15691 
15692  return SCIP_OKAY;
15693 }
15694 
15695 /** constraint enforcing method of constraint handler for relaxation solutions */
15696 static
15697 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15698 { /*lint --e{715}*/
15699  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15700 
15701  return SCIP_OKAY;
15702 }
15703 
15704 /** constraint enforcing method of constraint handler for pseudo solutions */
15705 static
15706 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15707 { /*lint --e{715}*/
15708  SCIP_CONSHDLRDATA* conshdlrdata;
15709  SCIP_Bool checkrelmaxabs;
15710  SCIP_Bool violated;
15711  int c;
15712 
15713  assert(scip != NULL);
15714  assert(conshdlr != NULL);
15715  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15716  assert(result != NULL);
15717 
15718  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15719  assert(conshdlrdata != NULL);
15720 
15721  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15722 
15723  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15724 
15725  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
15726  if( objinfeasible )
15727  {
15728  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
15729 
15730  *result = SCIP_DIDNOTRUN;
15731  return SCIP_OKAY;
15732  }
15733 
15734  /* check all linear constraints for feasibility */
15735  violated = FALSE;
15736  for( c = 0; c < nconss && !violated; ++c )
15737  {
15738  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
15739  }
15740 
15741  if( violated )
15742  *result = SCIP_INFEASIBLE;
15743  else
15744  *result = SCIP_FEASIBLE;
15745 
15746  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15747 
15748  return SCIP_OKAY;
15749 }
15750 
15751 
15752 /** feasibility check method of constraint handler for integral solutions */
15753 static
15754 SCIP_DECL_CONSCHECK(consCheckLinear)
15755 { /*lint --e{715}*/
15756  SCIP_CONSHDLRDATA* conshdlrdata;
15757  SCIP_Bool checkrelmaxabs;
15758  int c;
15759 
15760  assert(scip != NULL);
15761  assert(conshdlr != NULL);
15762  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15763  assert(result != NULL);
15764 
15765  *result = SCIP_FEASIBLE;
15766 
15767  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15768  assert(conshdlrdata != NULL);
15769 
15770  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15772  /*debugMsg(scip, "Check method of linear constraints\n");*/
15773 
15774  /* check all linear constraints for feasibility */
15775  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
15776  {
15777  SCIP_Bool violated = FALSE;
15778  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
15779 
15780  if( violated )
15781  {
15782  *result = SCIP_INFEASIBLE;
15783 
15784  if( printreason )
15785  {
15786  SCIP_CONSDATA* consdata;
15787  SCIP_Real activity;
15788 
15789  consdata = SCIPconsGetData(conss[c]);
15790  assert( consdata != NULL);
15791 
15792  activity = consdataGetActivity(scip, consdata, sol);
15793 
15794  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
15795  SCIPinfoMessage(scip, NULL, ";\n");
15796 
15797  if( activity == SCIP_INVALID ) /*lint !e777*/
15798  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
15799  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
15800  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
15801  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
15802  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
15803  }
15804  }
15805  }
15806 
15807  return SCIP_OKAY;
15808 }
15809 
15810 
15811 /** domain propagation method of constraint handler */
15812 static
15813 SCIP_DECL_CONSPROP(consPropLinear)
15814 { /*lint --e{715}*/
15815  SCIP_CONSHDLRDATA* conshdlrdata;
15816  SCIP_Bool rangedrowpropagation = FALSE;
15817  SCIP_Bool tightenbounds;
15818  SCIP_Bool cutoff;
15819 
15820  int nchgbds;
15821  int i;
15822 
15823  assert(scip != NULL);
15824  assert(conshdlr != NULL);
15825  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15826  assert(result != NULL);
15827 
15828  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15829  assert(conshdlrdata != NULL);
15831  /*debugMsg(scip, "Prop method of linear constraints\n");*/
15832 
15833  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
15834  if( SCIPinProbing(scip) )
15835  tightenbounds = TRUE;
15836  else
15837  {
15838  int depth;
15839  int propfreq;
15840  int tightenboundsfreq;
15841  int rangedrowfreq;
15842 
15843  depth = SCIPgetDepth(scip);
15844  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
15845  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
15846  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
15847  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
15848 
15849  /* check if we want to do ranged row propagation */
15850  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
15851  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
15852  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
15853  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
15854  rangedrowpropagation = rangedrowpropagation && (depth % rangedrowfreq == 0);
15855  }
15856 
15857  cutoff = FALSE;
15858  nchgbds = 0;
15859 
15860  /* process constraints marked for propagation */
15861  for( i = 0; i < nmarkedconss && !cutoff; i++ )
15862  {
15863  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
15864  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
15865  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
15866  }
15867 
15868  /* adjust result code */
15869  if( cutoff )
15870  *result = SCIP_CUTOFF;
15871  else if( nchgbds > 0 )
15872  *result = SCIP_REDUCEDDOM;
15873  else
15874  *result = SCIP_DIDNOTFIND;
15875 
15876  return SCIP_OKAY;
15877 }
15878 
15879 
15880 #define MAXCONSPRESOLROUNDS 10
15881 /** presolving method of constraint handler */
15882 static
15883 SCIP_DECL_CONSPRESOL(consPresolLinear)
15884 { /*lint --e{715}*/
15885  SCIP_CONSHDLRDATA* conshdlrdata;
15886  SCIP_CONS* cons;
15887  SCIP_CONSDATA* consdata;
15888  SCIP_Real minactivity;
15889  SCIP_Real maxactivity;
15890  SCIP_Bool minactisrelax;
15891  SCIP_Bool maxactisrelax;
15892  SCIP_Bool cutoff;
15893  int oldnfixedvars;
15894  int oldnaggrvars;
15895  int oldnchgbds;
15896  int oldndelconss;
15897  int oldnupgdconss;
15898  int oldnchgcoefs;
15899  int oldnchgsides;
15900  int firstchange;
15901  int firstupgradetry;
15902  int c;
15903 
15904  assert(scip != NULL);
15905  assert(conshdlr != NULL);
15906  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15907  assert(result != NULL);
15908 
15909  /*debugMsg(scip, "Presol method of linear constraints\n");*/
15910 
15911  /* remember old preprocessing counters */
15912  cutoff = FALSE;
15913  oldnfixedvars = *nfixedvars;
15914  oldnaggrvars = *naggrvars;
15915  oldnchgbds = *nchgbds;
15916  oldndelconss = *ndelconss;
15917  oldnupgdconss = *nupgdconss;
15918  oldnchgcoefs = *nchgcoefs;
15919  oldnchgsides = *nchgsides;
15920 
15921  /* get constraint handler data */
15922  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15923  assert(conshdlrdata != NULL);
15924 
15925  /* process single constraints */
15926  firstchange = INT_MAX;
15927  firstupgradetry = INT_MAX;
15928  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
15929  {
15930  int npresolrounds;
15931  SCIP_Bool infeasible;
15932 
15933  infeasible = FALSE;
15934 
15935  cons = conss[c];
15936  assert(SCIPconsIsActive(cons));
15937  consdata = SCIPconsGetData(cons);
15938  assert(consdata != NULL);
15939 
15940  if( consdata->eventdata == NULL )
15941  {
15942  /* catch bound change events of variables */
15943  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15944  assert(consdata->eventdata != NULL);
15945  }
15946 
15947  /* constraint should not be already presolved in the initial round */
15948  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
15949  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
15950  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
15951  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
15952 
15953  /* incorporate fixings and aggregations in constraint */
15954  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
15955 
15956  if( infeasible )
15957  {
15958  SCIPdebugMsg(scip, " -> infeasible fixing\n");
15959  cutoff = TRUE;
15960  break;
15961  }
15962 
15963  assert(consdata->removedfixings);
15964 
15965  /* we can only presolve linear constraints, that are not modifiable */
15966  if( SCIPconsIsModifiable(cons) )
15967  continue;
15968 
15969  /* remember the first changed constraint to begin the next aggregation round with */
15970  if( firstchange == INT_MAX && consdata->changed )
15971  firstchange = c;
15972 
15973  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
15974  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
15975  firstupgradetry = c;
15976 
15977  /* check, if constraint is already preprocessed */
15978  if( consdata->presolved )
15979  continue;
15980 
15981  assert(SCIPconsIsActive(cons));
15982 
15983  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
15984  SCIPdebugPrintCons(scip, cons, NULL);
15985 
15986  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
15987  * to avoid nearly infinite cycling due to very small bound changes)
15988  */
15989  npresolrounds = 0;
15990  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
15991  {
15992  assert(!cutoff);
15993  npresolrounds++;
15994 
15995  /* mark constraint being presolved and propagated */
15996  consdata->presolved = TRUE;
15997  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
15998 
15999  /* normalize constraint */
16000  SCIP_CALL( normalizeCons(scip, cons) );
16001 
16002  /* tighten left and right hand side due to integrality */
16003  SCIP_CALL( tightenSides(scip, cons, nchgsides) );
16004 
16005  /* check bounds */
16006  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16007  {
16008  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16009  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16010  cutoff = TRUE;
16011  break;
16012  }
16013 
16014  /* tighten variable's bounds */
16015  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16016  if( cutoff )
16017  break;
16018 
16019  /* check for fixed variables */
16020  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16021  if( cutoff )
16022  break;
16023 
16024  /* check constraint for infeasibility and redundancy */
16025  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
16026  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16027  {
16028  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16029  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16030  cutoff = TRUE;
16031  break;
16032  }
16033  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16034  {
16035  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16036  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16037  SCIP_CALL( SCIPdelCons(scip, cons) );
16038  assert(!SCIPconsIsActive(cons));
16039 
16040  if( !consdata->upgraded )
16041  (*ndelconss)++;
16042  break;
16043  }
16044  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
16045  {
16046  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16047  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16048  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16049  if( !consdata->upgraded )
16050  (*nchgsides)++;
16051  }
16052  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16053  {
16054  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16055  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16056  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16057  if( !consdata->upgraded )
16058  (*nchgsides)++;
16059  }
16060  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
16061 
16062  /* handle empty constraint */
16063  if( consdata->nvars == 0 )
16064  {
16065  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16066  {
16067  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16068  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16069  cutoff = TRUE;
16070  }
16071  else
16072  {
16073  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16074  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16075  SCIP_CALL( SCIPdelCons(scip, cons) );
16076  assert(!SCIPconsIsActive(cons));
16077 
16078  if( !consdata->upgraded )
16079  (*ndelconss)++;
16080  }
16081  break;
16082  }
16083 
16084  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16085  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16086 
16087  /* try to simplify inequalities */
16088  if( conshdlrdata->simplifyinequalities )
16089  {
16090  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides) );
16091  }
16092 
16093  /* aggregation variable in equations */
16094  if( conshdlrdata->aggregatevariables )
16095  {
16096  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16097  if( cutoff )
16098  break;
16099  }
16100  }
16101 
16102  if( !cutoff && !SCIPisStopped(scip) )
16103  {
16104  /* perform ranged row propagation */
16105  if( conshdlrdata->rangedrowpropagation )
16106  {
16107  int lastnfixedvars;
16108 
16109  lastnfixedvars = *nfixedvars;
16110 
16111  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16112  if( !cutoff )
16113  {
16114  if( lastnfixedvars < *nfixedvars )
16115  {
16116  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16117  }
16118  }
16119  }
16120 
16121  /* extract cliques from constraint */
16122  if( !cutoff && SCIPconsIsActive(cons) )
16123  {
16124  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16125  nfixedvars, nchgbds, &cutoff) );
16126 
16127  /* check if the constraint got redundant or infeasible */
16128  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16129  {
16130  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16131  {
16132  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16133  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16134  cutoff = TRUE;
16135  }
16136  else
16137  {
16138  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16139  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16140  SCIP_CALL( SCIPdelCons(scip, cons) );
16141  assert(!SCIPconsIsActive(cons));
16142 
16143  if( !consdata->upgraded )
16144  (*ndelconss)++;
16145  }
16146  }
16147  }
16148 
16149  /* convert special equalities */
16150  if( !cutoff && SCIPconsIsActive(cons) )
16151  {
16152  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16153  }
16154 
16155  /* apply dual presolving for variables that appear in only one constraint */
16156  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
16157  {
16158  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16159  }
16160 
16161  /* check if an inequality is parallel to the objective function */
16162  if( !cutoff && SCIPconsIsActive(cons) )
16163  {
16164  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16165  }
16166 
16167  /* remember the first changed constraint to begin the next aggregation round with */
16168  if( firstchange == INT_MAX && consdata->changed )
16169  firstchange = c;
16170 
16171  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16172  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16173  firstupgradetry = c;
16174  }
16175 
16176  /* singleton column stuffing */
16177  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16178  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowDualReds(scip) )
16179  {
16180  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16181  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16182 
16183  /* handle empty constraint */
16184  if( consdata->nvars == 0 )
16185  {
16186  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16187  {
16188  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16189  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16190  cutoff = TRUE;
16191  }
16192  else
16193  {
16194  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16195  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16196  SCIP_CALL( SCIPdelCons(scip, cons) );
16197  assert(!SCIPconsIsActive(cons));
16198 
16199  if( !consdata->upgraded )
16200  (*ndelconss)++;
16201  }
16202  break;
16203  }
16204  }
16205  }
16206 
16207  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16208  * only apply this expensive procedure in exhaustive presolving timing
16209  */
16210  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16211  {
16212  assert(firstchange >= 0);
16213 
16214  if( firstchange < nconss && conshdlrdata->presolusehashing )
16215  {
16216  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16217  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16218  ndelconss, nchgsides) );
16219  }
16220 
16221  if( firstchange < nconss && conshdlrdata->presolpairwise )
16222  {
16223  SCIP_CONS** usefulconss;
16224  int nusefulconss;
16225  int firstchangenew;
16226  SCIP_Longint npaircomparisons;
16227 
16228  npaircomparisons = 0;
16229  oldndelconss = *ndelconss;
16230  oldnchgsides = *nchgsides;
16231  oldnchgcoefs = *nchgcoefs;
16232 
16233  /* allocate temporary memory */
16234  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16235 
16236  nusefulconss = 0;
16237  firstchangenew = -1;
16238  for( c = 0; c < nconss; ++c )
16239  {
16240  /* update firstchange */
16241  if( c == firstchange )
16242  firstchangenew = nusefulconss;
16243 
16244  /* ignore inactive and modifiable constraints */
16245  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16246  continue;
16247 
16248  usefulconss[nusefulconss] = conss[c];
16249  ++nusefulconss;
16250  }
16251  firstchange = firstchangenew;
16252  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16253 
16254  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16255  {
16256  /* constraint has become inactive or modifiable during pairwise presolving */
16257  if( usefulconss[c] == NULL )
16258  continue;
16259 
16260  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16261 
16262  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16263  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16264  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16265 
16266  if( npaircomparisons > conshdlrdata->nmincomparisons )
16267  {
16268  assert(npaircomparisons > 0);
16269  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16270  break;
16271  oldndelconss = *ndelconss;
16272  oldnchgsides = *nchgsides;
16273  oldnchgcoefs = *nchgcoefs;
16274  npaircomparisons = 0;
16275  }
16276  }
16277  /* free temporary memory */
16278  SCIPfreeBufferArray(scip, &usefulconss);
16279  }
16280  }
16281 
16282  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16283  * in linear constraints and we therefore have full information about it
16284  */
16285  if( !cutoff && firstupgradetry < nconss
16286  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16287  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16288  )
16289  {
16290  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) && !SCIPisStopped(scip) )
16291  {
16292  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16293  }
16294  }
16295 
16296  /* try to upgrade constraints into a more specific constraint type;
16297  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16298  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16299  */
16300  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16301  {
16302  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16303  {
16304  cons = conss[c];
16305 
16306  /* don't upgrade modifiable constraints */
16307  if( SCIPconsIsModifiable(cons) )
16308  continue;
16309 
16310  consdata = SCIPconsGetData(cons);
16311  assert(consdata != NULL);
16312 
16313  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16314  if( consdata->upgradetried )
16315  continue;
16316  /* @todo force that upgrade will be performed later? */
16317  if( !consdata->presolved )
16318  continue;
16319 
16320  consdata->upgradetried = TRUE;
16321  if( SCIPconsIsActive(cons) )
16322  {
16323  SCIP_CONS* upgdcons;
16324 
16325  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16326  if( upgdcons != NULL )
16327  {
16328  /* add the upgraded constraint to the problem */
16329  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16330  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16331  (*nupgdconss)++;
16332 
16333  /* mark the linear constraint being upgraded and to be removed after presolving;
16334  * don't delete it directly, because it may help to preprocess other linear constraints
16335  */
16336  assert(!consdata->upgraded);
16337  consdata->upgraded = TRUE;
16338 
16339  /* delete upgraded inequalities immediately;
16340  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16341  */
16342  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16343  || !conshdlrdata->presolpairwise
16344  || (conshdlrdata->maxaggrnormscale == 0.0) )
16345  {
16346  SCIP_CALL( SCIPdelCons(scip, cons) );
16347  }
16348  }
16349  }
16350  }
16351  }
16352 
16353  /* return the correct result code */
16354  if( cutoff )
16355  *result = SCIP_CUTOFF;
16356  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16357  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16358  *result = SCIP_SUCCESS;
16359  else
16360  *result = SCIP_DIDNOTFIND;
16361 
16362  return SCIP_OKAY;
16363 }
16364 
16365 
16366 /** propagation conflict resolving method of constraint handler */
16367 static
16368 SCIP_DECL_CONSRESPROP(consRespropLinear)
16369 { /*lint --e{715}*/
16370 
16371  assert(scip != NULL);
16372  assert(cons != NULL);
16373  assert(result != NULL);
16374 
16375  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16376 
16377  return SCIP_OKAY;
16378 }
16379 
16380 
16381 /** variable rounding lock method of constraint handler */
16382 static
16383 SCIP_DECL_CONSLOCK(consLockLinear)
16384 { /*lint --e{715}*/
16385  SCIP_CONSDATA* consdata;
16386  SCIP_Bool haslhs;
16387  SCIP_Bool hasrhs;
16388  int i;
16389 
16390  assert(scip != NULL);
16391  assert(cons != NULL);
16392  consdata = SCIPconsGetData(cons);
16393  assert(consdata != NULL);
16394 
16395  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16396  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16397 
16398  /* update rounding locks of every single variable */
16399  for( i = 0; i < consdata->nvars; ++i )
16400  {
16401  if( SCIPisPositive(scip, consdata->vals[i]) )
16402  {
16403  if( haslhs )
16404  {
16405  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16406  }
16407  if( hasrhs )
16408  {
16409  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16410  }
16411  }
16412  else
16413  {
16414  if( haslhs )
16415  {
16416  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16417  }
16418  if( hasrhs )
16419  {
16420  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16421  }
16422  }
16423  }
16424 
16425  return SCIP_OKAY;
16426 }
16427 
16428 
16429 /** variable deletion method of constraint handler */
16430 static
16431 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16432 {
16433  assert(scip != NULL);
16434  assert(conshdlr != NULL);
16435  assert(conss != NULL || nconss == 0);
16436 
16437  if( nconss > 0 )
16438  {
16439  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16440  }
16441 
16442  return SCIP_OKAY;
16443 }
16444 
16445 /** constraint display method of constraint handler */
16446 static
16447 SCIP_DECL_CONSPRINT(consPrintLinear)
16448 { /*lint --e{715}*/
16449  assert(scip != NULL);
16450  assert(conshdlr != NULL);
16451  assert(cons != NULL);
16452 
16453  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16454 
16455  return SCIP_OKAY;
16456 }
16457 
16458 /** constraint copying method of constraint handler */
16459 static
16460 SCIP_DECL_CONSCOPY(consCopyLinear)
16461 { /*lint --e{715}*/
16462  SCIP_VAR** sourcevars;
16463  SCIP_Real* sourcecoefs;
16464  const char* consname;
16465  int nvars;
16466 
16467  assert(scip != NULL);
16468  assert(sourcescip != NULL);
16469  assert(sourcecons != NULL);
16470 
16471  /* get variables and coefficients of the source constraint */
16472  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16473  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16474  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16475 
16476  if( name != NULL )
16477  consname = name;
16478  else
16479  consname = SCIPconsGetName(sourcecons);
16480 
16481  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16482  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16483  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16484  assert(cons != NULL || *valid == FALSE);
16485 
16486  /* @todo should also the checkabsolute flag of the constraint be copied? */
16487 
16488  return SCIP_OKAY;
16489 }
16490 
16491 /* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
16492  * except for ranged rows for which exactly two operators '<=' must be present
16493  */
16494 static
16496  const char* str, /**< null terminated input string */
16497  char** firstoperator, /**< pointer to store the string starting at the first operator */
16498  char** secondoperator, /**< pointer to store the string starting at the second operator */
16499  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16500  )
16501 {
16502  char* curr;
16503 
16504  assert(str != NULL);
16505  assert(firstoperator != NULL);
16506  assert(secondoperator != NULL);
16507 
16508  *firstoperator = NULL;
16509  *secondoperator = NULL;
16510 
16511  curr = (char*)str;
16512  *success = TRUE;
16513 
16514  /* loop over the input string to find all operators */
16515  while( *curr && *success )
16516  {
16517  SCIP_Bool found = FALSE;
16518  int increment = 1;
16519 
16520  /* try if we found a possible operator */
16521  switch( *curr )
16522  {
16523  case '<':
16524  case '=':
16525  case '>':
16526 
16527  /* check if the two characters curr[0,1] form an operator together */
16528  if( curr[1] == '=' )
16529  {
16530  found = TRUE;
16531 
16532  /* update increment to continue after this operator */
16533  increment = 2;
16534  }
16535  break;
16536  case '[':
16537  if( strncmp(curr, "[free]", 6) == 0 )
16538  {
16539  found = TRUE;
16540 
16541  /* update increment to continue after this operator */
16542  increment = 6;
16543  }
16544  break;
16545  default:
16546  break;
16547 
16548  }
16549 
16550  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16551  if( found )
16552  {
16553  if( *firstoperator == NULL )
16554  {
16555  *firstoperator = curr;
16556  }
16557  else
16558  {
16559  if( *secondoperator != NULL )
16560  {
16561  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16562  *success = FALSE;
16563  }
16564  else if( strncmp(*firstoperator, "<=", 2) != 0 )
16565  {
16566  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16567  *success = FALSE;
16568  }
16569  else if( strncmp(curr, "<=", 2) != 0 )
16570  {
16571  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16572  *success = FALSE;
16573  }
16574 
16575  *secondoperator = curr;
16576  }
16577  }
16578 
16579  curr += increment;
16580  }
16581 
16582  /* check if we did find at least one operator */
16583  if( *success )
16584  {
16585  if( *firstoperator == NULL )
16586  {
16587  SCIPerrorMessage("Could not find any operator in line %s\n", str);
16588  *success = FALSE;
16589  }
16590  }
16591 
16592  return SCIP_OKAY;
16593 }
16594 
16595 /** constraint parsing method of constraint handler */
16596 static
16597 SCIP_DECL_CONSPARSE(consParseLinear)
16598 { /*lint --e{715}*/
16599  SCIP_VAR** vars;
16600  SCIP_Real* coefs;
16601  int nvars;
16602  int coefssize;
16603  int requsize;
16604  SCIP_Real lhs;
16605  SCIP_Real rhs;
16606  char* endptr;
16607  char* firstop;
16608  char* secondop;
16609  SCIP_Bool operatorsuccess;
16610  char* lhsstrptr;
16611  char* rhsstrptr;
16612  char* varstrptr;
16613 
16614  assert(scip != NULL);
16615  assert(success != NULL);
16616  assert(str != NULL);
16617  assert(name != NULL);
16618  assert(cons != NULL);
16619 
16620  /* set left and right hand side to their default values */
16621  lhs = -SCIPinfinity(scip);
16622  rhs = SCIPinfinity(scip);
16623 
16624  (*success) = FALSE;
16625 
16626  /* return of string empty */
16627  if( !*str )
16628  return SCIP_OKAY;
16629 
16630  /* ignore whitespace */
16631  while( isspace((unsigned char)*str) )
16632  ++str;
16633 
16634  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16635  * and the special word [free]
16636  */
16637  SCIP_CALL( findOperators(str, &firstop, &secondop, &operatorsuccess) );
16638 
16639  /* if the grammar is not valid for parsing a linear constraint, return */
16640  if( ! operatorsuccess )
16641  return SCIP_OKAY;
16642 
16643  varstrptr = (char *)str;
16644  lhsstrptr = rhsstrptr = NULL;
16645  assert(firstop != NULL);
16646 
16647  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16648  switch( *firstop )
16649  {
16650  case '<':
16651  assert(firstop[1] == '=');
16652  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16653  if( secondop != NULL )
16654  {
16655  assert(secondop[0] == '<' && secondop[1] == '=');
16656  lhsstrptr = (char *)str;
16657  varstrptr = firstop + 2;
16658  rhsstrptr = secondop + 2;
16659  }
16660  else
16661  {
16662  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16663  lhsstrptr = NULL;
16664  varstrptr = (char *)str;
16665  rhsstrptr = firstop + 2;
16666  }
16667  break;
16668  case '>':
16669  assert(firstop[1] == '=');
16670  assert(secondop == NULL);
16671  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16672  lhsstrptr = firstop + 2;
16673  break;
16674  case '=':
16675  assert(firstop[1] == '=');
16676  assert(secondop == NULL);
16677  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16678  rhsstrptr = firstop + 2;
16679  lhsstrptr = firstop + 2;
16680  break;
16681  case '[':
16682  assert(strncmp(firstop, "[free]", 6) == 0);
16683  assert(secondop == NULL);
16684  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16685  break;
16686  default:
16687  /* it should not be possible that a different character appears in that position */
16688  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16689  return SCIP_READERROR;
16690  }
16691 
16692  /* parse left hand side, if necessary */
16693  if( lhsstrptr != NULL )
16694  {
16695  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16696  {
16697  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16698  return SCIP_OKAY;
16699  }
16700 
16701  /* in case of an equation, assign the left also to the right hand side */
16702  if( rhsstrptr == lhsstrptr )
16703  rhs = lhs;
16704  }
16705 
16706  /* parse right hand side, if different from left hand side */
16707  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
16708  {
16709  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
16710  {
16711  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
16712  return SCIP_OKAY;
16713  }
16714  }
16715 
16716  /* initialize buffers for storing the variables and coefficients */
16717  coefssize = 100;
16718  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
16719  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
16720 
16721  assert(varstrptr != NULL);
16722 
16723  /* parse linear sum to get variables and coefficients */
16724  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16725 
16726  if( *success && requsize > coefssize )
16727  {
16728  /* realloc buffers and try again */
16729  coefssize = requsize;
16730  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
16731  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
16732 
16733  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16734  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
16735  }
16736 
16737  if( !*success )
16738  {
16739  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
16740  }
16741  else
16742  {
16743  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
16744  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
16745  }
16746 
16747  SCIPfreeBufferArray(scip, &coefs);
16748  SCIPfreeBufferArray(scip, &vars);
16749 
16750  return SCIP_OKAY;
16751 }
16752 
16753 
16754 /** constraint method of constraint handler which returns the variables (if possible) */
16755 static
16756 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
16757 { /*lint --e{715}*/
16758  SCIP_CONSDATA* consdata;
16759 
16760  consdata = SCIPconsGetData(cons);
16761  assert(consdata != NULL);
16762 
16763  if( varssize < consdata->nvars )
16764  (*success) = FALSE;
16765  else
16766  {
16767  assert(vars != NULL);
16768 
16769  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
16770  (*success) = TRUE;
16771  }
16772 
16773  return SCIP_OKAY;
16774 }
16775 
16776 /**! [Callback for the number of variables]*/
16777 /** constraint method of constraint handler which returns the number of variables (if possible) */
16778 static
16779 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
16780 { /*lint --e{715}*/
16781  SCIP_CONSDATA* consdata;
16782 
16783  consdata = SCIPconsGetData(cons);
16784  assert(consdata != NULL);
16785 
16786  (*nvars) = consdata->nvars;
16787  (*success) = TRUE;
16788 
16789  return SCIP_OKAY;
16790 }
16791 /**! [Callback for the number of variables]*/
16792 
16793 /*
16794  * Callback methods of event handler
16795  */
16797 static
16798 SCIP_DECL_EVENTEXEC(eventExecLinear)
16799 { /*lint --e{715}*/
16800  SCIP_CONS* cons;
16801  SCIP_CONSDATA* consdata;
16802  SCIP_VAR* var;
16803  SCIP_EVENTTYPE eventtype;
16804 
16805  assert(scip != NULL);
16806  assert(eventhdlr != NULL);
16807  assert(eventdata != NULL);
16808  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
16809  assert(event != NULL);
16810 
16811  cons = eventdata->cons;
16812  assert(cons != NULL);
16813  consdata = SCIPconsGetData(cons);
16814  assert(consdata != NULL);
16816  /* we can skip events droped for deleted constraints */
16817  if( SCIPconsIsDeleted(cons) )
16818  return SCIP_OKAY;
16819 
16820  eventtype = SCIPeventGetType(event);
16821  var = SCIPeventGetVar(event);
16822 
16823  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
16824  {
16825  SCIP_Real oldbound;
16826  SCIP_Real newbound;
16827  SCIP_Real val;
16828  int varpos;
16829 
16830  varpos = eventdata->varpos;
16831  assert(0 <= varpos && varpos < consdata->nvars);
16832  oldbound = SCIPeventGetOldbound(event);
16833  newbound = SCIPeventGetNewbound(event);
16834  assert(var != NULL);
16835  assert(consdata->vars[varpos] == var);
16836  val = consdata->vals[varpos];
16837 
16838  /* we only need to update the activities if the constraint is active,
16839  * otherwise we mark them to be invalid
16840  */
16841  if( SCIPconsIsActive(cons) )
16842  {
16843  /* update the activity values */
16844  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
16845  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
16846  else
16847  {
16848  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
16849  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
16850  }
16851  }
16852  else
16853  consdataInvalidateActivities(consdata);
16854 
16855  consdata->presolved = FALSE;
16856  consdata->rangedrowpropagated = 0;
16857 
16858  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
16859  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
16860  {
16861  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
16862 
16863  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16864  if( consdata->maxactdeltavar == var )
16865  {
16866  consdata->maxactdelta = SCIP_INVALID;
16867  consdata->maxactdeltavar = NULL;
16868  }
16869 
16870  /* check whether bound tightening might now be successful */
16871  if( consdata->boundstightened > 0)
16872  {
16873  switch( eventtype )
16874  {
16876  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
16877  consdata->boundstightened = 0;
16878  break;
16880  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
16881  consdata->boundstightened = 0;
16882  break;
16883  default:
16884  SCIPerrorMessage("invalid event type %d\n", eventtype);
16885  return SCIP_INVALIDDATA;
16886  }
16887  }
16888  }
16889  /* update maximal activity delta if a bound was relaxed */
16890  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
16891  {
16892  SCIP_Real lb;
16893  SCIP_Real ub;
16894  SCIP_Real domain;
16895  SCIP_Real delta;
16896 
16897  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
16898 
16899  lb = SCIPvarGetLbLocal(var);
16900  ub = SCIPvarGetUbLocal(var);
16901 
16902  domain = ub - lb;
16903  delta = REALABS(val) * domain;
16904 
16905  if( delta > consdata->maxactdelta )
16906  {
16907  consdata->maxactdelta = delta;
16908  consdata->maxactdeltavar = var;
16909  }
16910  }
16911  }
16912  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
16913  {
16914  /* we want to remove the fixed variable */
16915  consdata->presolved = FALSE;
16916  consdata->removedfixings = FALSE;
16917  consdata->rangedrowpropagated = 0;
16918 
16919  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16920  if( consdata->maxactdeltavar == var )
16921  {
16922  consdata->maxactdelta = SCIP_INVALID;
16923  consdata->maxactdeltavar = NULL;
16924  }
16925  }
16926 
16927  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
16928  {
16929  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
16930  assert(SCIPvarGetNLocksDown(var) <= 1);
16931  assert(SCIPvarGetNLocksUp(var) <= 1);
16932  consdata->presolved = FALSE;
16933  }
16934  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
16935  {
16936  SCIP_Real oldbound;
16937  SCIP_Real newbound;
16938  SCIP_Real val;
16939  int varpos;
16940 
16941  varpos = eventdata->varpos;
16942  assert(0 <= varpos && varpos < consdata->nvars);
16943  oldbound = SCIPeventGetOldbound(event);
16944  newbound = SCIPeventGetNewbound(event);
16945  assert(var != NULL);
16946  assert(consdata->vars[varpos] == var);
16947  val = consdata->vals[varpos];
16948 
16949  consdata->rangedrowpropagated = 0;
16950 
16951  /* update the activity values */
16952  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
16953  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
16954  else
16955  {
16956  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
16957  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
16958  }
16959  }
16960  else
16961  {
16962  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
16963  consdata->varsdeleted = TRUE;
16964  }
16965 
16966  return SCIP_OKAY;
16967 }
16968 
16969 
16970 /*
16971  * Callback methods of conflict handler
16972  */
16973 
16974 static
16975 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
16976 { /*lint --e{715}*/
16977  SCIP_VAR** vars;
16978  SCIP_Real* vals;
16979  SCIP_Real lhs;
16980  int i;
16981 
16982  assert(scip != NULL);
16983  assert(conflicthdlr != NULL);
16984  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
16985  assert(bdchginfos != NULL || nbdchginfos == 0);
16986  assert(result != NULL);
16987 
16988  /* don't process already resolved conflicts */
16989  if( resolved )
16990  {
16991  *result = SCIP_DIDNOTRUN;
16992  return SCIP_OKAY;
16993  }
16994 
16995  *result = SCIP_DIDNOTFIND;
16996 
16997  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
16998  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
16999  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17000  lhs = 1.0;
17001  for( i = 0; i < nbdchginfos; ++i )
17002  {
17003  assert(bdchginfos != NULL);
17004 
17005  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17006 
17007  /* we can only treat binary variables */
17008  /**@todo extend linear conflict constraints to some non-binary cases */
17009  if( !SCIPvarIsBinary(vars[i]) )
17010  break;
17011 
17012  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17013  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17014  vals[i] = 1.0;
17015  else
17016  {
17017  vals[i] = -1.0;
17018  lhs -= 1.0;
17019  }
17020  }
17021 
17022  if( i == nbdchginfos )
17023  {
17024  SCIP_CONS* cons;
17025  SCIP_CONS* upgdcons;
17026  char consname[SCIP_MAXSTRLEN];
17027 
17028  /* create a constraint out of the conflict set */
17029  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17030  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17031  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17032 
17033  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17034  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17035  if( upgdcons != NULL )
17036  {
17037  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17038  cons = upgdcons;
17039  }
17040 
17041  /* add conflict to SCIP */
17042  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17043 
17044  *result = SCIP_CONSADDED;
17045  }
17046 
17047  /* free temporary memory */
17048  SCIPfreeBufferArray(scip, &vals);
17049  SCIPfreeBufferArray(scip, &vars);
17050 
17051  return SCIP_OKAY;
17052 }
17053 
17054 
17055 /*
17056  * Quadratic constraint upgrading
17057  */
17058 
17059 
17060 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
17061  */
17062 static
17063 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
17064 { /*lint --e{715}*/
17065  SCIP_CONSDATA* upgdconsdata;
17066 
17067  assert(scip != NULL);
17068  assert(cons != NULL);
17069  assert(nupgdconss != NULL);
17070  assert(upgdconss != NULL);
17071 
17072  *nupgdconss = 0;
17073 
17074  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
17075  SCIPdebugPrintCons(scip, cons, NULL);
17076 
17077  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
17078  return SCIP_OKAY;
17079  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
17080  return SCIP_OKAY;
17081 
17082  if( upgdconsssize < 1 )
17083  {
17084  /* signal that we need more memory */
17085  *nupgdconss = -1;
17086  return SCIP_OKAY;
17087  }
17088 
17089  *nupgdconss = 1;
17090  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17091  SCIPgetNLinearVarsQuadratic(scip, cons),
17092  SCIPgetLinearVarsQuadratic(scip, cons),
17093  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
17094  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
17098  SCIPconsIsStickingAtNode(cons)) );
17099 
17100  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17101  assert(upgdconsdata != NULL);
17102 
17103  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original quadratic constraint */
17104  upgdconsdata->checkabsolute = TRUE;
17105 
17106  SCIPdebugMsg(scip, "created linear constraint:\n");
17107  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17108 
17109  return SCIP_OKAY;
17110 }
17111 
17112 /** tries to upgrade a nonlinear constraint into a linear constraint */
17113 static
17114 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17115 {
17116  SCIP_CONSDATA* upgdconsdata;
17117 
17118  assert(nupgdconss != NULL);
17119  assert(upgdconss != NULL);
17120 
17121  *nupgdconss = 0;
17122 
17123  /* no interest in nonlinear constraints */
17124  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
17125  return SCIP_OKAY;
17126 
17127  /* no interest in constant constraints */
17128  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
17129  return SCIP_OKAY;
17130 
17131  if( upgdconsssize < 1 )
17132  {
17133  /* request larger upgdconss array */
17134  *nupgdconss = -1;
17135  return SCIP_OKAY;
17136  }
17137 
17138  *nupgdconss = 1;
17139  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17141  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
17145  SCIPconsIsStickingAtNode(cons)) );
17146 
17147  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17148  assert(upgdconsdata != NULL);
17149 
17150  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17151  upgdconsdata->checkabsolute = TRUE;
17152 
17153  SCIPdebugMsg(scip, "created linear constraint:\n");
17154  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17155 
17156  return SCIP_OKAY;
17157 }
17158 
17159 /*
17160  * constraint specific interface methods
17161  */
17162 
17163 /** creates the handler for linear constraints and includes it in SCIP */
17165  SCIP* scip /**< SCIP data structure */
17166  )
17167 {
17168  SCIP_CONSHDLRDATA* conshdlrdata;
17169  SCIP_CONSHDLR* conshdlr;
17170  SCIP_EVENTHDLR* eventhdlr;
17171  SCIP_CONFLICTHDLR* conflicthdlr;
17172 
17173  assert(scip != NULL);
17174 
17175  /* create event handler for bound change events */
17177  eventExecLinear, NULL) );
17178 
17179  /* create conflict handler for linear constraints */
17181  conflictExecLinear, NULL) );
17182 
17183  /* create constraint handler data */
17184  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17185 
17186  /* include constraint handler */
17189  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17190  conshdlrdata) );
17191 
17192  assert(conshdlr != NULL);
17193 
17194  /* set non-fundamental callbacks via specific setter functions */
17195  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17196  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17197  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17198  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17199  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17200  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17201  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17202  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17203  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17204  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17205  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17206  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17207  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17208  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17209  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17210  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17212  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17213  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17215  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17216  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17217 
17218  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
17219  {
17220  /* include function that upgrades quadratic constraint to linear constraints */
17222  }
17223 
17224  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17225  {
17226  /* include the linear constraint upgrade in the nonlinear constraint handler */
17227  SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, upgradeConsNonlinear, NULL, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
17228  }
17229 
17230  /* add linear constraint handler parameters */
17231  SCIP_CALL( SCIPaddIntParam(scip,
17232  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17233  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17234  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17235  SCIP_CALL( SCIPaddIntParam(scip,
17236  "constraints/" CONSHDLR_NAME "/maxrounds",
17237  "maximal number of separation rounds per node (-1: unlimited)",
17238  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17239  SCIP_CALL( SCIPaddIntParam(scip,
17240  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17241  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17242  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17243  SCIP_CALL( SCIPaddIntParam(scip,
17244  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17245  "maximal number of cuts separated per separation round",
17246  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17247  SCIP_CALL( SCIPaddIntParam(scip,
17248  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17249  "maximal number of cuts separated per separation round in the root node",
17250  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17252  "constraints/" CONSHDLR_NAME "/presolpairwise",
17253  "should pairwise constraint comparison be performed in presolving?",
17254  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17256  "constraints/" CONSHDLR_NAME "/presolusehashing",
17257  "should hash table be used for detecting redundant constraints in advance",
17258  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17259  SCIP_CALL( SCIPaddIntParam(scip,
17260  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17261  "number for minimal pairwise presolve comparisons",
17262  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17264  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17265  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17266  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17268  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17269  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17270  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17272  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17273  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17274  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17276  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17277  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17278  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17280  "constraints/" CONSHDLR_NAME "/separateall",
17281  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17282  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17284  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17285  "should presolving search for aggregations in equations",
17286  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17288  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17289  "should presolving try to simplify inequalities",
17290  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17292  "constraints/" CONSHDLR_NAME "/dualpresolving",
17293  "should dual presolving steps be performed?",
17294  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17296  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17297  "should stuffing of singleton continuous variables be performed?",
17298  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17300  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17301  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17302  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17304  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17305  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17307  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17308  "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)?",
17309  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17311  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17312  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17313  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17315  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17316  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17317  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17319  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17320  "should presolving try to detect subsets of constraints parallel to the objective function?",
17321  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17323  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17324  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17325  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17327  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17328  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17329  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17330  SCIP_CALL( SCIPaddIntParam(scip,
17331  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17332  "maximum depth to apply ranged row propagation",
17333  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17334  SCIP_CALL( SCIPaddIntParam(scip,
17335  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17336  "frequency for applying ranged row propagation",
17337  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17339  "constraints/" CONSHDLR_NAME "/multaggrremove",
17340  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17341  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17342 
17343  return SCIP_OKAY;
17344 }
17345 
17346 /** includes a linear constraint update method into the linear constraint handler */
17348  SCIP* scip, /**< SCIP data structure */
17349  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17350  int priority, /**< priority of upgrading method */
17351  const char* conshdlrname /**< name of the constraint handler */
17352  )
17353 {
17354  SCIP_CONSHDLR* conshdlr;
17355  SCIP_CONSHDLRDATA* conshdlrdata;
17356  SCIP_LINCONSUPGRADE* linconsupgrade;
17357  char paramname[SCIP_MAXSTRLEN];
17358  char paramdesc[SCIP_MAXSTRLEN];
17359 
17360  assert(scip != NULL);
17361  assert(linconsupgd != NULL);
17362  assert(conshdlrname != NULL );
17363 
17364  /* find the linear constraint handler */
17365  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17366  if( conshdlr == NULL )
17367  {
17368  SCIPerrorMessage("linear constraint handler not found\n");
17369  return SCIP_PLUGINNOTFOUND;
17370  }
17371 
17372  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17373  assert(conshdlrdata != NULL);
17374 
17375  /* check if linear constraint update method already exists in constraint handler data */
17376  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17377  {
17378  /* create a linear constraint upgrade data object */
17379  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17380 
17381  /* insert linear constraint update method into constraint handler data */
17382  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17383 
17384  /* adds parameter to turn on and off the upgrading step */
17385  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17386  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17388  paramname, paramdesc,
17389  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17390  }
17391 
17392  return SCIP_OKAY;
17393 }
17394 
17395 /** creates and captures a linear constraint
17396  *
17397  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17398  */
17400  SCIP* scip, /**< SCIP data structure */
17401  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17402  const char* name, /**< name of constraint */
17403  int nvars, /**< number of nonzeros in the constraint */
17404  SCIP_VAR** vars, /**< array with variables of constraint entries */
17405  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17406  SCIP_Real lhs, /**< left hand side of constraint */
17407  SCIP_Real rhs, /**< right hand side of constraint */
17408  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17409  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17410  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17411  * Usually set to TRUE. */
17412  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17413  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17414  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17415  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17416  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17417  * Usually set to TRUE. */
17418  SCIP_Bool local, /**< is constraint only valid locally?
17419  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17420  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17421  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17422  * adds coefficients to this constraint. */
17423  SCIP_Bool dynamic, /**< is constraint subject to aging?
17424  * Usually set to FALSE. Set to TRUE for own cuts which
17425  * are separated as constraints. */
17426  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17427  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17428  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17429  * if it may be moved to a more global node?
17430  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17431  )
17432 {
17433  SCIP_CONSHDLR* conshdlr;
17434  SCIP_CONSDATA* consdata;
17435 
17436  assert(scip != NULL);
17437  assert(cons != NULL);
17438 
17439  /* find the linear constraint handler */
17440  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17441  if( conshdlr == NULL )
17442  {
17443  SCIPerrorMessage("linear constraint handler not found\n");
17444  return SCIP_PLUGINNOTFOUND;
17445  }
17446 
17447  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17448  * constraint after presolving we have to ensure that it holds active variables
17449  */
17450  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17451  {
17452  SCIP_VAR** consvars;
17453  SCIP_Real* consvals;
17454  SCIP_Real constant = 0.0;
17455  int nconsvars;
17456  int requiredsize;
17457 
17458  nconsvars = nvars;
17459  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17460  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17461 
17462  /* get active variables for new constraint */
17463  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17464 
17465  /* if space was not enough we need to resize the buffers */
17466  if( requiredsize > nconsvars )
17467  {
17468  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17469  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17470 
17471  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17472  assert(requiredsize <= nconsvars);
17473  }
17474 
17475  /* adjust sides and check that we do not subtract infinity values */
17476  if( SCIPisInfinity(scip, REALABS(constant)) )
17477  {
17478  if( constant < 0.0 )
17479  {
17480  if( SCIPisInfinity(scip, lhs) )
17481  {
17482  SCIPfreeBufferArray(scip, &consvals);
17483  SCIPfreeBufferArray(scip, &consvars);
17484 
17485  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);
17486 
17487  SCIPABORT();
17488  return SCIP_INVALIDDATA; /*lint !e527*/
17489  }
17490  if( SCIPisInfinity(scip, rhs) )
17491  {
17492  SCIPfreeBufferArray(scip, &consvals);
17493  SCIPfreeBufferArray(scip, &consvars);
17494 
17495  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);
17496 
17497  SCIPABORT();
17498  return SCIP_INVALIDDATA; /*lint !e527*/
17499  }
17500 
17501  lhs = -SCIPinfinity(scip);
17502  rhs = -SCIPinfinity(scip);
17503  }
17504  else
17505  {
17506  if( SCIPisInfinity(scip, -lhs) )
17507  {
17508  SCIPfreeBufferArray(scip, &consvals);
17509  SCIPfreeBufferArray(scip, &consvars);
17510 
17511  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);
17512 
17513  SCIPABORT();
17514  return SCIP_INVALIDDATA; /*lint !e527*/
17515  }
17516  if( SCIPisInfinity(scip, -rhs) )
17517  {
17518  SCIPfreeBufferArray(scip, &consvals);
17519  SCIPfreeBufferArray(scip, &consvars);
17520 
17521  SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17522 
17523  SCIPABORT();
17524  return SCIP_INVALIDDATA; /*lint !e527*/
17525  }
17526 
17527  lhs = SCIPinfinity(scip);
17528  rhs = SCIPinfinity(scip);
17529  }
17530  }
17531  else
17532  {
17533  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17534  lhs -= constant;
17535  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17536  rhs -= constant;
17537 
17538  if( SCIPisInfinity(scip, -lhs) )
17539  lhs = -SCIPinfinity(scip);
17540  else if( SCIPisInfinity(scip, lhs) )
17541  lhs = SCIPinfinity(scip);
17542 
17543  if( SCIPisInfinity(scip, rhs) )
17544  rhs = SCIPinfinity(scip);
17545  else if( SCIPisInfinity(scip, -rhs) )
17546  rhs = -SCIPinfinity(scip);
17547  }
17548 
17549  /* create constraint data */
17550  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17551  assert(consdata != NULL);
17552 
17553  SCIPfreeBufferArray(scip, &consvals);
17554  SCIPfreeBufferArray(scip, &consvars);
17555  }
17556  else
17557  {
17558  /* create constraint data */
17559  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17560  assert(consdata != NULL);
17561  }
17562 
17563  /* create constraint */
17564  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17565  local, modifiable, dynamic, removable, stickingatnode) );
17566 
17567  return SCIP_OKAY;
17568 }
17569 
17570 /** creates and captures a linear constraint
17571  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17572  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17573  *
17574  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17575  *
17576  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17577  */
17579  SCIP* scip, /**< SCIP data structure */
17580  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17581  const char* name, /**< name of constraint */
17582  int nvars, /**< number of nonzeros in the constraint */
17583  SCIP_VAR** vars, /**< array with variables of constraint entries */
17584  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17585  SCIP_Real lhs, /**< left hand side of constraint */
17586  SCIP_Real rhs /**< right hand side of constraint */
17587  )
17588 {
17589  assert(scip != NULL);
17590 
17591  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17592  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17593 
17594  return SCIP_OKAY;
17596 
17597 /** creates by copying and captures a linear constraint */
17599  SCIP* scip, /**< target SCIP data structure */
17600  SCIP_CONS** cons, /**< pointer to store the created target constraint */
17601  SCIP* sourcescip, /**< source SCIP data structure */
17602  const char* name, /**< name of constraint */
17603  int nvars, /**< number of variables in source variable array */
17604  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17605  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17606  SCIP_Real lhs, /**< left hand side of the linear constraint */
17607  SCIP_Real rhs, /**< right hand side of the linear constraint */
17608  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17609  * variables of the target SCIP */
17610  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17611  * target constraints */
17612  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17613  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17614  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17615  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17616  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17617  SCIP_Bool local, /**< is constraint only valid locally? */
17618  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17619  SCIP_Bool dynamic, /**< is constraint subject to aging? */
17620  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17621  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17622  * if it may be moved to a more global node? */
17623  SCIP_Bool global, /**< create a global or a local copy? */
17624  SCIP_Bool* valid /**< pointer to store if the copying was valid */
17625  )
17626 {
17627  SCIP_VAR** vars;
17628  SCIP_Real* coefs;
17629 
17630  SCIP_Real constant;
17631  int requiredsize;
17632  int v;
17633  SCIP_Bool success;
17634 
17635  if( SCIPisGT(scip, lhs, rhs) )
17636  {
17637  *valid = FALSE;
17638  return SCIP_OKAY;
17639  }
17640 
17641  (*valid) = TRUE;
17642 
17643  if( nvars == 0 )
17644  {
17645  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17646  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17647  return SCIP_OKAY;
17648  }
17649 
17650  /* duplicate variable array */
17651  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17652 
17653  /* duplicate coefficient array */
17654  if( sourcecoefs != NULL )
17655  {
17656  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17657  }
17658  else
17659  {
17660  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
17661  for( v = 0; v < nvars; ++v )
17662  coefs[v] = 1.0;
17663  }
17664 
17665  constant = 0.0;
17666 
17667  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17668  * the target SCIP
17669  */
17670  if( !SCIPvarIsOriginal(vars[0]) )
17671  {
17672  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
17673 
17674  if( requiredsize > nvars )
17675  {
17676  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
17677  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
17678 
17679  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
17680  assert(requiredsize <= nvars);
17681  }
17682  }
17683  else
17684  {
17685  for( v = 0; v < nvars; ++v )
17686  {
17687  assert(SCIPvarIsOriginal(vars[v]));
17688  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
17689  assert(vars[v] != NULL);
17690  }
17691  }
17692 
17693 
17694  success = TRUE;
17695  /* map variables of the source constraint to variables of the target SCIP */
17696  for( v = 0; v < nvars && success; ++v )
17697  {
17698  SCIP_VAR* var;
17699  var = vars[v];
17700 
17701  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
17702  assert(!(success) || vars[v] != NULL);
17703  }
17704 
17705  /* only create the target constraint, if all variables could be copied */
17706  if( success )
17707  {
17708  if( !SCIPisInfinity(scip, -lhs) )
17709  lhs -= constant;
17710 
17711  if( !SCIPisInfinity(scip, rhs) )
17712  rhs -= constant;
17713 
17714  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17715  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17716  }
17717  else
17718  *valid = FALSE;
17719 
17720  /* free buffer array */
17721  SCIPfreeBufferArray(scip, &coefs);
17722  SCIPfreeBufferArray(scip, &vars);
17723 
17724  return SCIP_OKAY;
17725 }
17726 
17727 /** adds coefficient to linear constraint (if it is not zero) */
17729  SCIP* scip, /**< SCIP data structure */
17730  SCIP_CONS* cons, /**< constraint data */
17731  SCIP_VAR* var, /**< variable of constraint entry */
17732  SCIP_Real val /**< coefficient of constraint entry */
17733  )
17734 {
17735  assert(scip != NULL);
17736  assert(cons != NULL);
17737  assert(var != NULL);
17738 
17739  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17740  {
17741  SCIPerrorMessage("constraint is not linear\n");
17742  return SCIP_INVALIDDATA;
17743  }
17744 
17745  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17746  * constraint after presolving we have to ensure that it holds active variables
17747  */
17748  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
17749  {
17750  SCIP_CONSDATA* consdata;
17751  SCIP_VAR** consvars;
17752  SCIP_Real* consvals;
17753  SCIP_Real constant = 0.0;
17754  SCIP_Real rhs;
17755  SCIP_Real lhs;
17756  int nconsvars;
17757  int requiredsize;
17758  int v;
17759 
17760  nconsvars = 1;
17761  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
17762  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
17763  consvars[0] = var;
17764  consvals[0] = val;
17765 
17766  /* get active variables for new constraint */
17767  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17768 
17769  /* if space was not enough we need to resize the buffers */
17770  if( requiredsize > nconsvars )
17771  {
17772  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17773  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17774 
17775  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17776  assert(requiredsize <= nconsvars);
17777  }
17778 
17779  consdata = SCIPconsGetData(cons);
17780  assert(consdata != NULL);
17781 
17782  lhs = consdata->lhs;
17783  rhs = consdata->rhs;
17784 
17785  /* adjust sides and check that we do not subtract infinity values */
17786  /* constant is infinite */
17787  if( SCIPisInfinity(scip, REALABS(constant)) )
17788  {
17789  if( constant < 0.0 )
17790  {
17791  if( SCIPisInfinity(scip, lhs) )
17792  {
17793  SCIPfreeBufferArray(scip, &consvals);
17794  SCIPfreeBufferArray(scip, &consvars);
17795 
17796  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));
17797 
17798  SCIPABORT();
17799  return SCIP_INVALIDDATA; /*lint !e527*/
17800  }
17801  if( SCIPisInfinity(scip, rhs) )
17802  {
17803  SCIPfreeBufferArray(scip, &consvals);
17804  SCIPfreeBufferArray(scip, &consvars);
17805 
17806  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));
17807 
17808  SCIPABORT();
17809  return SCIP_INVALIDDATA; /*lint !e527*/
17810  }
17811 
17812  lhs = -SCIPinfinity(scip);
17813  rhs = -SCIPinfinity(scip);
17814  }
17815  else
17816  {
17817  if( SCIPisInfinity(scip, -lhs) )
17818  {
17819  SCIPfreeBufferArray(scip, &consvals);
17820  SCIPfreeBufferArray(scip, &consvars);
17821 
17822  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));
17823 
17824  SCIPABORT();
17825  return SCIP_INVALIDDATA; /*lint !e527*/
17826  }
17827  if( SCIPisInfinity(scip, -rhs) )
17828  {
17829  SCIPfreeBufferArray(scip, &consvals);
17830  SCIPfreeBufferArray(scip, &consvars);
17831 
17832  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));
17833 
17834  SCIPABORT();
17835  return SCIP_INVALIDDATA; /*lint !e527*/
17836  }
17837 
17838  lhs = SCIPinfinity(scip);
17839  rhs = SCIPinfinity(scip);
17840  }
17841  }
17842  /* constant is not infinite */
17843  else
17844  {
17845  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17846  lhs -= constant;
17847  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17848  rhs -= constant;
17849 
17850  if( SCIPisInfinity(scip, -lhs) )
17851  lhs = -SCIPinfinity(scip);
17852  else if( SCIPisInfinity(scip, lhs) )
17853  lhs = SCIPinfinity(scip);
17854 
17855  if( SCIPisInfinity(scip, rhs) )
17856  rhs = SCIPinfinity(scip);
17857  else if( SCIPisInfinity(scip, -rhs) )
17858  rhs = -SCIPinfinity(scip);
17859  }
17860 
17861  /* add all active variables to constraint */
17862  for( v = nconsvars - 1; v >= 0; --v )
17863  {
17864  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
17865  }
17866 
17867  /* update left and right hand sides */
17868  SCIP_CALL( chgLhs(scip, cons, lhs));
17869  SCIP_CALL( chgRhs(scip, cons, rhs));
17870 
17871  SCIPfreeBufferArray(scip, &consvals);
17872  SCIPfreeBufferArray(scip, &consvars);
17873  }
17874  else
17875  {
17876  SCIP_CALL( addCoef(scip, cons, var, val) );
17877  }
17878 
17879  return SCIP_OKAY;
17880 }
17881 
17882 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
17883  * not yet contained in the constraint
17884  *
17885  * @note This method may only be called during problem creation stage for an original constraint and variable.
17886  *
17887  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17888  */
17890  SCIP* scip, /**< SCIP data structure */
17891  SCIP_CONS* cons, /**< constraint data */
17892  SCIP_VAR* var, /**< variable of constraint entry */
17893  SCIP_Real val /**< new coefficient of constraint entry */
17894  )
17895 {
17896  SCIP_CONSDATA* consdata;
17897  SCIP_VAR** vars;
17898  SCIP_Bool found;
17899  int i;
17900 
17901  assert(scip != NULL);
17902  assert(cons != NULL);
17903  assert(var != NULL);
17904 
17905  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17906  {
17907  SCIPerrorMessage("constraint is not linear\n");
17908  return SCIP_INVALIDDATA;
17909  }
17910 
17911  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
17912  {
17913  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
17914  return SCIP_INVALIDDATA;
17915  }
17916 
17917  consdata = SCIPconsGetData(cons);
17918  assert(consdata != NULL);
17919 
17920  vars = consdata->vars;
17921  found = FALSE;
17922  i = 0;
17923  while( i < consdata->nvars )
17924  {
17925  if( vars[i] == var )
17926  {
17927  if( found || SCIPisZero(scip, val) )
17928  {
17929  SCIP_CALL( delCoefPos(scip, cons, i) );
17930 
17931  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
17932  i--;
17933  }
17934  else
17935  {
17936  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
17937  }
17938  found = TRUE;
17939  }
17940  i++;
17941  }
17942 
17943  if( !found && !SCIPisZero(scip, val) )
17944  {
17945  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
17946  }
17947 
17948  return SCIP_OKAY;
17949 }
17950 
17951 /** deletes variable from linear constraint
17952  *
17953  * @note This method may only be called during problem creation stage for an original constraint and variable.
17954  *
17955  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17956  */
17958  SCIP* scip, /**< SCIP data structure */
17959  SCIP_CONS* cons, /**< constraint data */
17960  SCIP_VAR* var /**< variable of constraint entry */
17961  )
17962 {
17963  assert(scip != NULL);
17964  assert(cons != NULL);
17965  assert(var != NULL);
17966 
17967  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
17968 
17969  return SCIP_OKAY;
17970 }
17971 
17972 /** gets left hand side of linear constraint */
17974  SCIP* scip, /**< SCIP data structure */
17975  SCIP_CONS* cons /**< constraint data */
17976  )
17977 {
17978  SCIP_CONSDATA* consdata;
17979 
17980  assert(cons != NULL);
17981 
17982  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17983  {
17984  SCIPerrorMessage("constraint is not linear\n");
17985  SCIPABORT();
17986  return SCIP_INVALID; /*lint !e527*/
17987  }
17988 
17989  consdata = SCIPconsGetData(cons);
17990  assert(consdata != NULL);
17991 
17992  return consdata->lhs;
17993 }
17994 
17995 /** gets right hand side of linear constraint */
17997  SCIP* scip, /**< SCIP data structure */
17998  SCIP_CONS* cons /**< constraint data */
17999  )
18000 {
18001  SCIP_CONSDATA* consdata;
18002 
18003  assert(cons != NULL);
18004 
18005  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18006  {
18007  SCIPerrorMessage("constraint is not linear\n");
18008  SCIPABORT();
18009  return SCIP_INVALID; /*lint !e527*/
18010  }
18011 
18012  consdata = SCIPconsGetData(cons);
18013  assert(consdata != NULL);
18014 
18015  return consdata->rhs;
18016 }
18017 
18018 /** changes left hand side of linear constraint */
18020  SCIP* scip, /**< SCIP data structure */
18021  SCIP_CONS* cons, /**< constraint data */
18022  SCIP_Real lhs /**< new left hand side */
18023  )
18024 {
18025  assert(scip != NULL);
18026  assert(cons != NULL);
18027 
18028  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18029  {
18030  SCIPerrorMessage("constraint is not linear\n");
18031  return SCIP_INVALIDDATA;
18032  }
18033 
18034  SCIP_CALL( chgLhs(scip, cons, lhs) );
18035 
18036  return SCIP_OKAY;
18037 }
18038 
18039 /** changes right hand side of linear constraint */
18041  SCIP* scip, /**< SCIP data structure */
18042  SCIP_CONS* cons, /**< constraint data */
18043  SCIP_Real rhs /**< new right hand side */
18044  )
18045 {
18046  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18047  {
18048  SCIPerrorMessage("constraint is not linear\n");
18049  return SCIP_INVALIDDATA;
18050  }
18051 
18052  SCIP_CALL( chgRhs(scip, cons, rhs) );
18053 
18054  return SCIP_OKAY;
18055 }
18056 
18057 /** gets the number of variables in the linear constraint */
18058 int SCIPgetNVarsLinear(
18059  SCIP* scip, /**< SCIP data structure */
18060  SCIP_CONS* cons /**< constraint data */
18061  )
18062 {
18063  SCIP_CONSDATA* consdata;
18064 
18065  assert(cons != NULL);
18066 
18067  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18068  {
18069  SCIPerrorMessage("constraint is not linear\n");
18070  SCIPABORT();
18071  return -1; /*lint !e527*/
18072  }
18073 
18074  consdata = SCIPconsGetData(cons);
18075  assert(consdata != NULL);
18076 
18077  return consdata->nvars;
18078 }
18079 
18080 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18082  SCIP* scip, /**< SCIP data structure */
18083  SCIP_CONS* cons /**< constraint data */
18084  )
18085 {
18086  SCIP_CONSDATA* consdata;
18087 
18088  assert(cons != NULL);
18089 
18090  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18091  {
18092  SCIPerrorMessage("constraint is not linear\n");
18093  SCIPABORT();
18094  return NULL; /*lint !e527*/
18095  }
18096 
18097  consdata = SCIPconsGetData(cons);
18098  assert(consdata != NULL);
18099 
18100  return consdata->vars;
18101 }
18102 
18103 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18105  SCIP* scip, /**< SCIP data structure */
18106  SCIP_CONS* cons /**< constraint data */
18107  )
18108 {
18109  SCIP_CONSDATA* consdata;
18110 
18111  assert(cons != NULL);
18112 
18113  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18114  {
18115  SCIPerrorMessage("constraint is not linear\n");
18116  SCIPABORT();
18117  return NULL; /*lint !e527*/
18118  }
18119 
18120  consdata = SCIPconsGetData(cons);
18121  assert(consdata != NULL);
18122 
18123  return consdata->vals;
18124 }
18125 
18126 /** gets the activity of the linear constraint in the given solution
18127  *
18128  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18129  * comprises positive and negative infinity contributions
18130  */
18132  SCIP* scip, /**< SCIP data structure */
18133  SCIP_CONS* cons, /**< constraint data */
18134  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18135  )
18136 {
18137  SCIP_CONSDATA* consdata;
18138 
18139  assert(cons != NULL);
18140 
18141  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18142  {
18143  SCIPerrorMessage("constraint is not linear\n");
18144  SCIPABORT();
18145  return SCIP_INVALID; /*lint !e527*/
18146  }
18147 
18148  consdata = SCIPconsGetData(cons);
18149  assert(consdata != NULL);
18150 
18151  if( consdata->row != NULL )
18152  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18153  else
18154  return consdataGetActivity(scip, consdata, sol);
18155 }
18156 
18157 /** gets the feasibility of the linear constraint in the given solution */
18159  SCIP* scip, /**< SCIP data structure */
18160  SCIP_CONS* cons, /**< constraint data */
18161  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18162  )
18163 {
18164  SCIP_CONSDATA* consdata;
18165 
18166  assert(cons != NULL);
18167 
18168  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18169  {
18170  SCIPerrorMessage("constraint is not linear\n");
18171  SCIPABORT();
18172  return SCIP_INVALID; /*lint !e527*/
18173  }
18174 
18175  consdata = SCIPconsGetData(cons);
18176  assert(consdata != NULL);
18177 
18178  if( consdata->row != NULL )
18179  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18180  else
18181  return consdataGetFeasibility(scip, consdata, sol);
18182 }
18183 
18184 /** gets the dual solution of the linear constraint in the current LP */
18186  SCIP* scip, /**< SCIP data structure */
18187  SCIP_CONS* cons /**< constraint data */
18188  )
18189 {
18190  SCIP_CONSDATA* consdata;
18191 
18192  assert(cons != NULL);
18193  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18194 
18195  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18196  {
18197  SCIPerrorMessage("constraint is not linear\n");
18198  SCIPABORT();
18199  return SCIP_INVALID; /*lint !e527*/
18200  }
18201 
18202  consdata = SCIPconsGetData(cons);
18203  assert(consdata != NULL);
18204 
18205  if( consdata->row != NULL )
18206  return SCIProwGetDualsol(consdata->row);
18207  else
18208  return 0.0;
18209 }
18210 
18211 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18213  SCIP* scip, /**< SCIP data structure */
18214  SCIP_CONS* cons /**< constraint data */
18215  )
18216 {
18217  SCIP_CONSDATA* consdata;
18218 
18219  assert(cons != NULL);
18220  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18221 
18222  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18223  {
18224  SCIPerrorMessage("constraint is not linear\n");
18225  SCIPABORT();
18226  return SCIP_INVALID; /*lint !e527*/
18227  }
18228 
18229  consdata = SCIPconsGetData(cons);
18230  assert(consdata != NULL);
18231 
18232  if( consdata->row != NULL )
18233  return SCIProwGetDualfarkas(consdata->row);
18234  else
18235  return 0.0;
18236 }
18237 
18238 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18239  * the user must not modify the row!
18240  */
18242  SCIP* scip, /**< SCIP data structure */
18243  SCIP_CONS* cons /**< constraint data */
18244  )
18245 {
18246  SCIP_CONSDATA* consdata;
18247 
18248  assert(cons != NULL);
18249 
18250  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18251  {
18252  SCIPerrorMessage("constraint is not linear\n");
18253  SCIPABORT();
18254  return NULL; /*lint !e527*/
18255  }
18256 
18257  consdata = SCIPconsGetData(cons);
18258  assert(consdata != NULL);
18259 
18260  return consdata->row;
18261 }
18262 
18263 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18265  SCIP* scip, /**< SCIP data structure */
18266  SCIP_CONS* cons, /**< source constraint to try to convert */
18267  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18268  )
18269 {
18270  SCIP_CONSHDLR* conshdlr;
18271  SCIP_CONSHDLRDATA* conshdlrdata;
18272  SCIP_CONSDATA* consdata;
18273  SCIP_VAR* var;
18274  SCIP_Real val;
18275  SCIP_Real lb;
18276  SCIP_Real ub;
18277  SCIP_Real poscoeffsum;
18278  SCIP_Real negcoeffsum;
18279  SCIP_Bool integral;
18280  int nposbin;
18281  int nnegbin;
18282  int nposint;
18283  int nnegint;
18284  int nposimpl;
18285  int nnegimpl;
18286  int nposimplbin;
18287  int nnegimplbin;
18288  int nposcont;
18289  int nnegcont;
18290  int ncoeffspone;
18291  int ncoeffsnone;
18292  int ncoeffspint;
18293  int ncoeffsnint;
18294  int ncoeffspfrac;
18295  int ncoeffsnfrac;
18296  int i;
18297 
18298  assert(scip != NULL);
18299  assert(cons != NULL);
18300  assert(upgdcons != NULL);
18301 
18302  *upgdcons = NULL;
18303 
18304  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18305  if( SCIPconsIsModifiable(cons) )
18306  return SCIP_OKAY;
18307 
18308  /* check for upgradability */
18309  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18310  return SCIP_OKAY;
18311 
18312  /* get the constraint handler and check, if it's really a linear constraint */
18313  conshdlr = SCIPconsGetHdlr(cons);
18314  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18315  {
18316  SCIPerrorMessage("constraint is not linear\n");
18317  return SCIP_INVALIDDATA;
18318  }
18319 
18320  /* get constraint handler data and constraint data */
18321  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18322  assert(conshdlrdata != NULL);
18323  consdata = SCIPconsGetData(cons);
18324  assert(consdata != NULL);
18325 
18326  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18327  if( consdata->upgraded )
18328  return SCIP_OKAY;
18329 
18330  /* check, if the constraint is already stored as LP row */
18331  if( consdata->row != NULL )
18332  {
18333  if( SCIProwIsInLP(consdata->row) )
18334  {
18335  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18336  return SCIP_INVALIDDATA;
18337  }
18338  else
18339  {
18340  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18341  }
18342  }
18343 
18344  /* normalize constraint */
18345  SCIP_CALL( normalizeCons(scip, cons) );
18346 
18347 
18348  /*
18349  * calculate some statistics on linear constraint
18350  */
18351 
18352  nposbin = 0;
18353  nnegbin = 0;
18354  nposint = 0;
18355  nnegint = 0;
18356  nposimpl = 0;
18357  nnegimpl = 0;
18358  nposimplbin = 0;
18359  nnegimplbin = 0;
18360  nposcont = 0;
18361  nnegcont = 0;
18362  ncoeffspone = 0;
18363  ncoeffsnone = 0;
18364  ncoeffspint = 0;
18365  ncoeffsnint = 0;
18366  ncoeffspfrac = 0;
18367  ncoeffsnfrac = 0;
18368  integral = TRUE;
18369  poscoeffsum = 0.0;
18370  negcoeffsum = 0.0;
18371 
18372  for( i = 0; i < consdata->nvars; ++i )
18373  {
18374  var = consdata->vars[i];
18375  val = consdata->vals[i];
18376  lb = SCIPvarGetLbLocal(var);
18377  ub = SCIPvarGetUbLocal(var);
18378  assert(!SCIPisZero(scip, val));
18379 
18380  switch( SCIPvarGetType(var) )
18381  {
18382  case SCIP_VARTYPE_BINARY:
18383  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18384  integral = integral && SCIPisIntegral(scip, val);
18385  if( val >= 0.0 )
18386  nposbin++;
18387  else
18388  nnegbin++;
18389  break;
18390  case SCIP_VARTYPE_INTEGER:
18391  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18392  integral = integral && SCIPisIntegral(scip, val);
18393  if( val >= 0.0 )
18394  nposint++;
18395  else
18396  nnegint++;
18397  break;
18398  case SCIP_VARTYPE_IMPLINT:
18399  if( SCIPvarIsBinary(var) )
18400  {
18401  if( val >= 0.0 )
18402  nposimplbin++;
18403  else
18404  nnegimplbin++;
18405  }
18406  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18407  integral = integral && SCIPisIntegral(scip, val);
18408  if( val >= 0.0 )
18409  nposimpl++;
18410  else
18411  nnegimpl++;
18412  break;
18414  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18415  if( val >= 0.0 )
18416  nposcont++;
18417  else
18418  nnegcont++;
18419  break;
18420  default:
18421  SCIPerrorMessage("unknown variable type\n");
18422  return SCIP_INVALIDDATA;
18423  }
18424  if( SCIPisEQ(scip, val, 1.0) )
18425  ncoeffspone++;
18426  else if( SCIPisEQ(scip, val, -1.0) )
18427  ncoeffsnone++;
18428  else if( SCIPisIntegral(scip, val) )
18429  {
18430  if( SCIPisPositive(scip, val) )
18431  ncoeffspint++;
18432  else
18433  ncoeffsnint++;
18434  }
18435  else
18436  {
18437  if( SCIPisPositive(scip, val) )
18438  ncoeffspfrac++;
18439  else
18440  ncoeffsnfrac++;
18441  }
18442  if( SCIPisPositive(scip, val) )
18443  poscoeffsum += val;
18444  else
18445  negcoeffsum += val;
18446  }
18447 
18448 
18449  /*
18450  * call the upgrading methods
18451  */
18452 
18453  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18454  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18455  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",
18456  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18457  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18458  poscoeffsum, negcoeffsum, integral);
18459 
18460  /* try all upgrading methods in priority order in case the upgrading step is enable */
18461  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18462  {
18463  if( conshdlrdata->linconsupgrades[i]->active )
18464  {
18465  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18466  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18467  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18468  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18469  poscoeffsum, negcoeffsum, integral,
18470  upgdcons) );
18471  }
18472  }
18473 
18474 #ifdef SCIP_DEBUG
18475  if( *upgdcons != NULL )
18476  {
18477  SCIPdebugPrintCons(scip, cons, NULL);
18478  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18479  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18480  }
18481 #endif
18482 
18483  return SCIP_OKAY;
18484 }
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:47357
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28366
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:19205
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:41453
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6669
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1399
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:46437
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:3928
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:22517
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3110
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19643
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47292
#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:47305
#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:19503
#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:3131
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:1566
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:138
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1504
#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:41220
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:43447
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7682
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:47655
#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:9293
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:5309
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:43475
#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:46677
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:28394
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:12657
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:46807
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:30662
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip.c:27953
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47082
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47733
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2024
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: scip.c:47840
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47009
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:2254
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:18951
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:28106
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18760
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:47381
#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:47344
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:2828
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3189
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:21979
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:47022
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47094
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:2890
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:28624
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip.c:13402
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:27245
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21654
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:7445
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:27149
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22633
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides)
Definition: cons_linear.c:8783
#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:12902
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:46957
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:5696
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:21947
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:37028
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:1499
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:3176
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:16501
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:2270
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18992
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:11986
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:4978
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:27578
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:46409
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:18208
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:76
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27178
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47429
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:77
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:9453
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:47417
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:16692
#define MAXCONSPRESOLROUNDS
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27127
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:47640
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:27878
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:25473
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5187
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:7108
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24216
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:25812
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:5240
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:2451
#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:47759
#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:12585
#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:46970
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:13210
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25862
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13291
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:2550
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:22744
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:19305
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1375
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:24088
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:3531
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:421
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46725
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2097
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3262
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21782
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2047
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:8866
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:5043
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28596
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3807
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:5094
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:43271
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5211
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47331
#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:5378
#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:19249
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:13796
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47318
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:2350
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27529
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:3995
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34655
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:29202
#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:7535
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
Definition: scip.c:47045
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2154
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:127
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21847
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:3410
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47230
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:30579
#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:4079
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1349
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:30396
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3042
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43039
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6937
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:29085
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:4484
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7392
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:30555
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:2001
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:41266
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17868
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2288
#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:17613
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:25569
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:42044
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16514
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21708
#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:12034
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
Definition: scip.c:43013
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:47785
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47033
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:31105
#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:22813
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:11851
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:35830
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:116
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7368
#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:11806
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:2596
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:17842
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip.c:13513
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:3156
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30534
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:5638
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:46996
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:2677
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47106
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:11486
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:22926
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:47059
static SCIP_DECL_CONSLOCK(consLockLinear)
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip.c:27903
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1428
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:12856
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:7817
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip.c:1870
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27755
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:25879
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:47369
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:9349
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11761
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:25678
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4138
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18726
#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:6941
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:30688
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:9407
#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:47118
#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:4555
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:25842
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:31154
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3653
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:62
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
Definition: scip.c:46493
#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:31128
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:7750
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1323
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47070
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46983
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:9463
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:47393
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:13043
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:47155
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:17729
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:38905
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:11086
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:4796
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8700
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47143
#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:1951
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:42878
#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:1976
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:27853
#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)