Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Michael Winkler
23  * @author Gerald Gamrath
24  * @author Domenico Salvagnin
25  *
26  * Linear constraints are separated with a high priority, because they are easy
27  * to separate. Instead of using the global cut pool, the same effect can be
28  * implemented by adding linear constraints to the root node, such that they are
29  * separated each time, the linear constraints are separated. A constraint
30  * handler, which generates linear constraints in this way should have a lower
31  * separation priority than the linear constraint handler, and it should have a
32  * separation frequency that is a multiple of the frequency of the linear
33  * constraint handler. In this way, it can be avoided to separate the same cut
34  * twice, because if a separation run of the handler is always preceded by a
35  * separation of the linear constraints, the priorily added constraints are
36  * always satisfied.
37  *
38  * Linear constraints are enforced and checked with a very low priority. Checking
39  * of (many) linear constraints is much more involved than checking the solution
40  * values for integrality. Because we are separating the linear constraints quite
41  * often, it is only necessary to enforce them for integral solutions. A constraint
42  * handler which generates pool cuts in its enforcing method should have an
43  * enforcing priority smaller than that of the linear constraint handler to avoid
44  * regenerating constraints which already exist.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include <assert.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <ctype.h>
53 
54 #include "scip/cons_linear.h"
55 #include "scip/cons_knapsack.h"
56 #include "scip/cons_quadratic.h"
57 #include "scip/cons_nonlinear.h"
58 #include "scip/pub_misc.h"
59 #include "scip/debug.h"
60 
61 #define CONSHDLR_NAME "linear"
62 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
63 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
64 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
65 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
66 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
67 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
68 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
69  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
70 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
71 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
72 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
73 #define CONSHDLR_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
74 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
75 
76 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
77 
78 #define EVENTHDLR_NAME "linear"
79 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
80 
81 #define CONFLICTHDLR_NAME "linear"
82 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
83 #define CONFLICTHDLR_PRIORITY -1000000
84 
85 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
86 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
87 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
88 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
89 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
90 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
91 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
92 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
93 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
94  * comparison round */
95 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
96  * propagation? */
97 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
98  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
99 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
100  * (0.0: disable constraint aggregation) */
101 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
102  * to best node's dual bound for separating knapsack cardinality cuts */
103 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
104  * the ones with non-zero dual value? */
105 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
106 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
107 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
108 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
109  * function defining an upper bound and prevent these constraints from
110  * entering the LP */
111 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
112  * function defining a lower bound and prevent these constraints from
113  * entering the LP */
114 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
115  * objective function */
116 
117 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
118 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
119 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
120  * type
121  */
122 
123 #define HASHSIZE_LINEARCONS 131101 /**< minimal size of hash table in linear constraint tables */
124 
125 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
126 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
127 
128 #ifdef WITH_PRINTORIGCONSTYPES
129 /** constraint type */
130 enum SCIP_Constype
131 {
132  SCIP_CONSTYPE_EMPTY = 0, /**< */
133  SCIP_CONSTYPE_FREE = 1, /**< */
134  SCIP_CONSTYPE_SINGLETON = 2, /**< */
135  SCIP_CONSTYPE_AGGREGATION = 3, /**< */
136  SCIP_CONSTYPE_VARBOUND = 4, /**< */
137  SCIP_CONSTYPE_SETPARTITION = 5, /**< */
138  SCIP_CONSTYPE_SETPACKING = 6, /**< */
139  SCIP_CONSTYPE_SETCOVERING = 7, /**< */
140  SCIP_CONSTYPE_CARDINALITY = 8, /**< */
141  SCIP_CONSTYPE_INVKNAPSACK = 9, /**< */
142  SCIP_CONSTYPE_EQKNAPSACK = 10, /**< */
143  SCIP_CONSTYPE_BINPACKING = 11, /**< */
144  SCIP_CONSTYPE_KNAPSACK = 12, /**< */
145  SCIP_CONSTYPE_INTKNAPSACK = 13, /**< */
146  SCIP_CONSTYPE_MIXEDBINARY = 14, /**< */
147  SCIP_CONSTYPE_GENERAL = 15 /**< */
148 };
149 typedef enum SCIP_Constype SCIP_CONSTYPE;
150 #endif
151 
152 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
153  * maybe in fullDualPresolve(), see convertLongEquality()
154  */
155 
156 
157 /** constraint data for linear constraints */
158 struct SCIP_ConsData
159 {
160  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
161  SCIP_Real rhs; /**< right hand side of row */
162  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
163  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
164  * activity, ignoring the coefficients contributing with infinite value */
165  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
166  * activity, ignoring the coefficients contributing with infinite value */
167  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
168  * over all contributing values */
169  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
170  * over all contributing values */
171  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
172  * activity, ignoring the coefficients contributing with infinite value */
173  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
174  * activity, ignoring the coefficients contributing with infinite value */
175  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
176  * over all contributing values */
177  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
178  * over all contributing values */
179  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
180  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
181  SCIP_Longint possignature; /**< bit signature of coefficients that may take a positive value */
182  SCIP_Longint negsignature; /**< bit signature of coefficients that may take a negative value */
183  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
184  SCIP_VAR** vars; /**< variables of constraint entries */
185  SCIP_Real* vals; /**< coefficients of constraint entries */
186  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
187  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
188  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
189  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
190  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
191  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
192  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
193  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
194  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
195  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
196  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
197  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
198  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
199  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
200  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
201  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
202  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
203  int varssize; /**< size of the vars- and vals-arrays */
204  int nvars; /**< number of nonzeros in constraint */
205  int nbinvars; /**< the number of binary variables in the constraint, only valid after
206  * sorting in stage >= SCIP_STAGE_INITSOLVE
207  */
208  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
209  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
210  unsigned int validminact:1; /**< is the local minactivity valid? */
211  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
212  unsigned int validglbminact:1; /**< is the global minactivity valid? */
213  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
214  unsigned int propagated:1; /**< is constraint already propagated? */
215  unsigned int boundstightened:1; /**< is constraint already propagated with bound tightening? */
216  unsigned int presolved:1; /**< is constraint already presolved? */
217  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
218  unsigned int validsignature:1; /**< is the bit signature valid? */
219  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
220  unsigned int normalized:1; /**< is the constraint in normalized form? */
221  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
222  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
223  unsigned int sorted:1; /**< are the constraint's variables sorted? */
224  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
225  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
226  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
227  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
228  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
229  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
230  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
231  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
232 };
233 
234 /** event data for bound change event */
235 struct SCIP_EventData
236 {
237  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
238  int varpos; /**< position of variable in vars array */
239  int filterpos; /**< position of event in variable's event filter */
240 };
241 
242 /** constraint handler data */
243 struct SCIP_ConshdlrData
244 {
245  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
246  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
247  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
248  * (0.0: disable constraint aggregation) */
249  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
250  * to best node's dual bound for separating knapsack cardinality cuts */
251  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
252  int linconsupgradessize;/**< size of linconsupgrade array */
253  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
254  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
255  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
256  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
257  int maxsepacuts; /**< maximal number of cuts separated per separation round */
258  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
259  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
260  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
261  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
262  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
263  * the ones with non-zero dual value? */
264  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
265  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
266  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
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 
279 };
280 
281 /** linear constraint update method */
282 struct SCIP_LinConsUpgrade
283 {
284  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
285  int priority; /**< priority of upgrading method */
286  SCIP_Bool active; /**< is upgrading enabled */
287 };
288 
289 
290 /*
291  * Propagation rules
292  */
293 
294 enum Proprule
295 {
296  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
297  * variable due to the right hand side of the inequality */
298  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
299  * variable due to the left hand side of the inequality */
300  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
301 };
302 typedef enum Proprule PROPRULE;
303 
304 /** inference information */
305 struct InferInfo
306 {
307  union
308  {
309  struct
310  {
311  unsigned int proprule:8; /**< propagation rule that was applied */
312  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
313  } asbits;
314  int asint; /**< inference information as a single int value */
315  } val;
316 };
317 typedef struct InferInfo INFERINFO;
318 
319 /** converts an integer into an inference information */
320 static
322  int i /**< integer to convert */
323  )
324 {
325  INFERINFO inferinfo;
326 
327  inferinfo.val.asint = i;
328 
329  return inferinfo;
330 }
332 /** converts an inference information into an int */
333 static
334 int inferInfoToInt(
335  INFERINFO inferinfo /**< inference information to convert */
336  )
337 {
338  return inferinfo.val.asint;
339 }
340 
341 /** returns the propagation rule stored in the inference information */
342 static
344  INFERINFO inferinfo /**< inference information to convert */
345  )
346 {
347  return (int) inferinfo.val.asbits.proprule;
348 }
349 
350 /** returns the position stored in the inference information */
351 static
352 int inferInfoGetPos(
353  INFERINFO inferinfo /**< inference information to convert */
354  )
355 {
356  return (int) inferinfo.val.asbits.pos;
357 }
358 
359 /** constructs an inference information out of a propagation rule and a position number */
360 static
362  PROPRULE proprule, /**< propagation rule that deduced the value */
363  int pos /**< variable position, the propagation rule was applied at */
364  )
365 {
366  INFERINFO inferinfo;
367  assert( pos >= 0 );
368 
369  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
370  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
371 
372  return inferinfo;
373 }
374 
375 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
376 static
377 int getInferInt(
378  PROPRULE proprule, /**< propagation rule that deduced the value */
379  int pos /**< variable position, the propagation rule was applied at */
380  )
381 {
382  return inferInfoToInt(getInferInfo(proprule, pos));
383 }
384 
385 
386 /*
387  * memory growing methods for dynamically allocated arrays
388  */
389 
390 /** ensures, that linconsupgrades array can store at least num entries */
391 static
393  SCIP* scip, /**< SCIP data structure */
394  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
395  int num /**< minimum number of entries to store */
396  )
397 {
398  assert(scip != NULL);
399  assert(conshdlrdata != NULL);
400  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
401 
402  if( num > conshdlrdata->linconsupgradessize )
403  {
404  int newsize;
405 
406  newsize = SCIPcalcMemGrowSize(scip, num);
407  SCIP_CALL( SCIPreallocMemoryArray(scip, &conshdlrdata->linconsupgrades, newsize) );
408  conshdlrdata->linconsupgradessize = newsize;
409  }
410  assert(num <= conshdlrdata->linconsupgradessize);
411 
412  return SCIP_OKAY;
413 }
414 
415 /** ensures, that vars and vals arrays can store at least num entries */
416 static
418  SCIP* scip, /**< SCIP data structure */
419  SCIP_CONSDATA* consdata, /**< linear constraint data */
420  int num /**< minimum number of entries to store */
421  )
422 {
423  assert(scip != NULL);
424  assert(consdata != NULL);
425  assert(consdata->nvars <= consdata->varssize);
426 
427  if( num > consdata->varssize )
428  {
429  int newsize;
430 
431  newsize = SCIPcalcMemGrowSize(scip, num);
432  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
433  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
434  if( consdata->eventdata != NULL )
435  {
436  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
437  }
438  consdata->varssize = newsize;
439  }
440  assert(num <= consdata->varssize);
441 
442  return SCIP_OKAY;
443 }
444 
445 
446 /*
447  * local methods for managing linear constraint update methods
448  */
449 
450 /** creates a linear constraint upgrade data object */
451 static
453  SCIP* scip, /**< SCIP data structure */
454  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
455  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
456  int priority /**< priority of upgrading method */
457  )
458 {
459  assert(scip != NULL);
460  assert(linconsupgrade != NULL);
461  assert(linconsupgd != NULL);
462 
463  SCIP_CALL( SCIPallocMemory(scip, linconsupgrade) );
464  (*linconsupgrade)->linconsupgd = linconsupgd;
465  (*linconsupgrade)->priority = priority;
466  (*linconsupgrade)->active = TRUE;
467 
468  return SCIP_OKAY;
469 }
470 
471 /** frees a linear constraint upgrade data object */
472 static
473 void linconsupgradeFree(
474  SCIP* scip, /**< SCIP data structure */
475  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
476  )
477 {
478  assert(scip != NULL);
479  assert(linconsupgrade != NULL);
480  assert(*linconsupgrade != NULL);
481 
482  SCIPfreeMemory(scip, linconsupgrade);
483 }
484 
485 /** creates constraint handler data for linear constraint handler */
486 static
488  SCIP* scip, /**< SCIP data structure */
489  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
490  SCIP_EVENTHDLR* eventhdlr /**< event handler */
491  )
492 {
493  assert(scip != NULL);
494  assert(conshdlrdata != NULL);
495  assert(eventhdlr != NULL);
496 
497  SCIP_CALL( SCIPallocMemory(scip, conshdlrdata) );
498  (*conshdlrdata)->linconsupgrades = NULL;
499  (*conshdlrdata)->linconsupgradessize = 0;
500  (*conshdlrdata)->nlinconsupgrades = 0;
502  /* set event handler for updating linear constraint activity bounds */
503  (*conshdlrdata)->eventhdlr = eventhdlr;
504 
505  return SCIP_OKAY;
506 }
507 
508 /** frees constraint handler data for linear constraint handler */
509 static
510 void conshdlrdataFree(
511  SCIP* scip, /**< SCIP data structure */
512  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
513  )
514 {
515  int i;
516 
517  assert(scip != NULL);
518  assert(conshdlrdata != NULL);
519  assert(*conshdlrdata != NULL);
520 
521  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
522  {
523  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
524  }
525  SCIPfreeMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades);
526 
527  SCIPfreeMemory(scip, conshdlrdata);
528 }
529 
530 /** creates a linear constraint upgrade data object */
531 static
533  SCIP* scip, /**< SCIP data structure */
534  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
535  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
536  const char* conshdlrname /**< name of the constraint handler */
537  )
538 {
539  int i;
540 
541  assert(scip != NULL);
542  assert(conshdlrdata != NULL);
543  assert(linconsupgd != NULL);
544  assert(conshdlrname != NULL);
545 
546  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
547  {
548  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
549  {
550 #ifdef SCIP_DEBUG
551  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
552 #endif
553  return TRUE;
554  }
555  }
556 
557  return FALSE;
558 }
559 
560 /** adds a linear constraint update method to the constraint handler's data */
561 static
563  SCIP* scip, /**< SCIP data structure */
564  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
565  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
566  )
567 {
568  int i;
569 
570  assert(scip != NULL);
571  assert(conshdlrdata != NULL);
572  assert(linconsupgrade != NULL);
573 
574  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
575 
576  for( i = conshdlrdata->nlinconsupgrades;
577  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
578  {
579  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
580  }
581  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
582  conshdlrdata->linconsupgrades[i] = linconsupgrade;
583  conshdlrdata->nlinconsupgrades++;
584 
585  return SCIP_OKAY;
586 }
587 
588 /*
589  * local methods
590  */
591 
592 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
593 static
595  SCIP* scip, /**< SCIP data structure */
596  SCIP_CONS* cons, /**< linear constraint */
597  SCIP_VAR* var, /**< variable of constraint entry */
598  SCIP_Real val /**< coefficient of constraint entry */
599  )
600 {
601  SCIP_CONSDATA* consdata;
602 
603  assert(scip != NULL);
604  assert(cons != NULL);
605  assert(var != NULL);
606 
607  consdata = SCIPconsGetData(cons);
608  assert(consdata != NULL);
609  assert(!SCIPisZero(scip, val));
610 
611  if( SCIPisPositive(scip, val) )
612  {
613  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
614  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
615  }
616  else
617  {
618  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
619  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
620  }
621 
622  return SCIP_OKAY;
623 }
624 
625 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
626 static
628  SCIP* scip, /**< SCIP data structure */
629  SCIP_CONS* cons, /**< linear constraint */
630  SCIP_VAR* var, /**< variable of constraint entry */
631  SCIP_Real val /**< coefficient of constraint entry */
632  )
633 {
634  SCIP_CONSDATA* consdata;
635 
636  assert(scip != NULL);
637  assert(cons != NULL);
638  assert(var != NULL);
639 
640  consdata = SCIPconsGetData(cons);
641  assert(consdata != NULL);
642  assert(!SCIPisZero(scip, val));
643 
644  if( SCIPisPositive(scip, val) )
645  {
646  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
647  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
648  }
649  else
650  {
651  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
652  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
653  }
654 
655  return SCIP_OKAY;
656 }
657 
658 /** creates event data for variable at given position, and catches events */
659 static
661  SCIP* scip, /**< SCIP data structure */
662  SCIP_CONS* cons, /**< linear constraint */
663  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
664  int pos /**< array position of variable to catch bound change events for */
665  )
666 {
667  SCIP_CONSDATA* consdata;
668  assert(scip != NULL);
669  assert(cons != NULL);
670  assert(eventhdlr != NULL);
671 
672  consdata = SCIPconsGetData(cons);
673  assert(consdata != NULL);
675  assert(0 <= pos && pos < consdata->nvars);
676  assert(consdata->vars != NULL);
677  assert(consdata->vars[pos] != NULL);
678  assert(SCIPvarIsTransformed(consdata->vars[pos]));
679  assert(consdata->eventdata != NULL);
680  assert(consdata->eventdata[pos] == NULL);
681 
682  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
683  consdata->eventdata[pos]->cons = cons;
684  consdata->eventdata[pos]->varpos = pos;
685 
686  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
689  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
690 
691  return SCIP_OKAY;
692 }
693 
694 /** deletes event data for variable at given position, and drops events */
695 static
697  SCIP* scip, /**< SCIP data structure */
698  SCIP_CONS* cons, /**< linear constraint */
699  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
700  int pos /**< array position of variable to catch bound change events for */
701  )
702 {
703  SCIP_CONSDATA* consdata;
704  assert(scip != NULL);
705  assert(cons != NULL);
706  assert(eventhdlr != NULL);
707 
708  consdata = SCIPconsGetData(cons);
709  assert(consdata != NULL);
711  assert(0 <= pos && pos < consdata->nvars);
712  assert(consdata->vars[pos] != NULL);
713  assert(consdata->eventdata != NULL);
714  assert(consdata->eventdata[pos] != NULL);
715  assert(consdata->eventdata[pos]->cons == cons);
716  assert(consdata->eventdata[pos]->varpos == pos);
717 
718  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
721  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
722 
723  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
724 
725  return SCIP_OKAY;
726 }
727 
728 /** catches bound change events for all variables in transformed linear constraint */
729 static
731  SCIP* scip, /**< SCIP data structure */
732  SCIP_CONS* cons, /**< linear constraint */
733  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
734  )
735 {
736  SCIP_CONSDATA* consdata;
737  int i;
738 
739  assert(scip != NULL);
740  assert(cons != NULL);
741 
742  consdata = SCIPconsGetData(cons);
743  assert(consdata != NULL);
744  assert(consdata->eventdata == NULL);
745 
746  /* allocate eventdata array */
747  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
748  assert(consdata->eventdata != NULL);
749  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
750 
751  /* catch event for every single variable */
752  for( i = 0; i < consdata->nvars; ++i )
753  {
754  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
755  }
756 
757  return SCIP_OKAY;
758 }
759 
760 /** drops bound change events for all variables in transformed linear constraint */
761 static
763  SCIP* scip, /**< SCIP data structure */
764  SCIP_CONS* cons, /**< linear constraint */
765  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
766  )
767 {
768  SCIP_CONSDATA* consdata;
769  int i;
770 
771  assert(scip != NULL);
772  assert(cons != NULL);
773 
774  consdata = SCIPconsGetData(cons);
775  assert(consdata != NULL);
776  assert(consdata->eventdata != NULL);
777 
778  /* drop event of every single variable */
779  for( i = consdata->nvars - 1; i >= 0; --i )
780  {
781  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
782  }
783 
784  /* free eventdata array */
785  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
786  assert(consdata->eventdata == NULL);
787 
788  return SCIP_OKAY;
789 }
790 
791 /** returns whether we are in a stage, where the variable events should be caught */
792 static
794  SCIP* scip /**< SCIP data structure */
795  )
796 {
797  assert(scip != NULL);
798 
800 }
801 
802 /** creates a linear constraint data */
803 static
805  SCIP* scip, /**< SCIP data structure */
806  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
807  int nvars, /**< number of nonzeros in the constraint */
808  SCIP_VAR** vars, /**< array with variables of constraint entries */
809  SCIP_Real* vals, /**< array with coefficients of constraint entries */
810  SCIP_Real lhs, /**< left hand side of row */
811  SCIP_Real rhs /**< right hand side of row */
812  )
813 {
814  int v;
815 
816  assert(scip != NULL);
817  assert(consdata != NULL);
818  assert(nvars == 0 || vars != NULL);
819  assert(nvars == 0 || vals != NULL);
820 
821  if( SCIPisInfinity(scip, rhs) )
822  rhs = SCIPinfinity(scip);
823  else if( SCIPisInfinity(scip, -rhs) )
824  rhs = -SCIPinfinity(scip);
825 
826  if( SCIPisInfinity(scip, -lhs) )
827  lhs = -SCIPinfinity(scip);
828  else if( SCIPisInfinity(scip, lhs) )
829  lhs = SCIPinfinity(scip);
830 
831  if( SCIPisGT(scip, lhs, rhs) )
832  {
833  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
834  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
835  }
836 
837  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
838 
839  (*consdata)->varssize = nvars;
840  (*consdata)->nvars = nvars;
841  (*consdata)->hascontvar = FALSE;
842  (*consdata)->hasnonbinvar = FALSE;
843  (*consdata)->hasnonbinvalid = TRUE;
844  if( nvars > 0 )
845  {
846  int k;
847 
848  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
849  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, vals, nvars) );
850  k = 0;
851  for( v = 0; v < nvars; ++v )
852  {
853  assert((*consdata)->vars[v] != NULL);
854  if( !SCIPisZero(scip, (*consdata)->vals[v]) )
855  {
856  (*consdata)->vars[k] = (*consdata)->vars[v];
857  (*consdata)->vals[k] = (*consdata)->vals[v];
858  k++;
859 
860  /* update hascontvar and hasnonbinvar flags */
861  if( !(*consdata)->hascontvar )
862  {
863  SCIP_VARTYPE vartype = SCIPvarGetType((*consdata)->vars[v]);
864 
865  if( vartype != SCIP_VARTYPE_BINARY )
866  {
867  (*consdata)->hasnonbinvar = TRUE;
868 
869  if( vartype == SCIP_VARTYPE_CONTINUOUS )
870  (*consdata)->hascontvar = TRUE;
871  }
872  }
873  }
874  }
875  (*consdata)->nvars = k;
876  }
877  else
878  {
879  (*consdata)->vars = NULL;
880  (*consdata)->vals = NULL;
881  }
882  (*consdata)->eventdata = NULL;
883 
884  (*consdata)->row = NULL;
885  (*consdata)->lhs = lhs;
886  (*consdata)->rhs = rhs;
887  (*consdata)->maxabsval = SCIP_INVALID;
888  (*consdata)->minactivity = SCIP_INVALID;
889  (*consdata)->maxactivity = SCIP_INVALID;
890  (*consdata)->lastminactivity = SCIP_INVALID;
891  (*consdata)->lastmaxactivity = SCIP_INVALID;
892  (*consdata)->maxactdelta = SCIP_INVALID;
893  (*consdata)->maxactdeltavar = NULL;
894  (*consdata)->minactivityneginf = -1;
895  (*consdata)->minactivityposinf = -1;
896  (*consdata)->maxactivityneginf = -1;
897  (*consdata)->maxactivityposinf = -1;
898  (*consdata)->minactivityneghuge = -1;
899  (*consdata)->minactivityposhuge = -1;
900  (*consdata)->maxactivityneghuge = -1;
901  (*consdata)->maxactivityposhuge = -1;
902  (*consdata)->glbminactivity = SCIP_INVALID;
903  (*consdata)->glbmaxactivity = SCIP_INVALID;
904  (*consdata)->lastglbminactivity = SCIP_INVALID;
905  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
906  (*consdata)->glbminactivityneginf = -1;
907  (*consdata)->glbminactivityposinf = -1;
908  (*consdata)->glbmaxactivityneginf = -1;
909  (*consdata)->glbmaxactivityposinf = -1;
910  (*consdata)->glbminactivityneghuge = -1;
911  (*consdata)->glbminactivityposhuge = -1;
912  (*consdata)->glbmaxactivityneghuge = -1;
913  (*consdata)->glbmaxactivityposhuge = -1;
914  (*consdata)->possignature = 0;
915  (*consdata)->negsignature = 0;
916  (*consdata)->validmaxabsval = FALSE;
917  (*consdata)->validactivities = FALSE;
918  (*consdata)->validminact = FALSE;
919  (*consdata)->validmaxact = FALSE;
920  (*consdata)->validglbminact = FALSE;
921  (*consdata)->validglbmaxact = FALSE;
922  (*consdata)->propagated = FALSE;
923  (*consdata)->boundstightened = FALSE;
924  (*consdata)->presolved = FALSE;
925  (*consdata)->removedfixings = FALSE;
926  (*consdata)->validsignature = FALSE;
927  (*consdata)->changed = TRUE;
928  (*consdata)->normalized = FALSE;
929  (*consdata)->upgradetried = FALSE;
930  (*consdata)->upgraded = FALSE;
931  (*consdata)->sorted = (nvars <= 1);
932  (*consdata)->merged = (nvars <= 1);
933  (*consdata)->cliquesadded = FALSE;
934  (*consdata)->implsadded = FALSE;
935  (*consdata)->binvarssorted = FALSE;
936  (*consdata)->nbinvars = -1;
937  (*consdata)->varsdeleted = FALSE;
938 
939  if( SCIPisTransformed(scip) )
940  {
941  /* get transformed variables */
942  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
943  }
944 
945  /* capture variables */
946  for( v = 0; v < (*consdata)->nvars; v++ )
947  {
948  assert((*consdata)->vars[v] != NULL);
949  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
950  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
951  }
952 
953  return SCIP_OKAY;
954 }
955 
956 /** frees a linear constraint data */
957 static
959  SCIP* scip, /**< SCIP data structure */
960  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
961  )
962 {
963  int v;
964 
965  assert(scip != NULL);
966  assert(consdata != NULL);
967  assert(*consdata != NULL);
968  assert((*consdata)->varssize >= 0);
969 
970  /* release the row */
971  if( (*consdata)->row != NULL )
972  {
973  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
974  }
975 
976  /* release variables */
977  for( v = 0; v < (*consdata)->nvars; v++ )
978  {
979  assert((*consdata)->vars[v] != NULL);
980  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
981  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
982  }
983 
984  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
985  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
986  SCIPfreeBlockMemory(scip, consdata);
987 
988  return SCIP_OKAY;
989 }
990 
991 /** prints linear constraint in CIP format to file stream */
992 static
994  SCIP* scip, /**< SCIP data structure */
995  SCIP_CONSDATA* consdata, /**< linear constraint data */
996  FILE* file /**< output file (or NULL for standard output) */
997  )
998 {
999  assert(scip != NULL);
1000  assert(consdata != NULL);
1001 
1002  /* print left hand side for ranged rows */
1003  if( !SCIPisInfinity(scip, -consdata->lhs)
1004  && !SCIPisInfinity(scip, consdata->rhs)
1005  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1006  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1008  /* print coefficients and variables */
1009  if( consdata->nvars == 0 )
1010  SCIPinfoMessage(scip, file, "0");
1011  else
1012  {
1013  /* post linear sum of the linear constraint */
1014  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1015  }
1016 
1017  /* print right hand side */
1018  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1019  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1020  else if( !SCIPisInfinity(scip, consdata->rhs) )
1021  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1022  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1023  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1024  else
1025  SCIPinfoMessage(scip, file, " [free]");
1026 
1027  return SCIP_OKAY;
1028 }
1029 
1030 /** invalidates activity bounds, such that they are recalculated in next get */
1031 static
1033  SCIP_CONSDATA* consdata /**< linear constraint */
1034  )
1035 {
1036  assert(consdata != NULL);
1037 
1038  consdata->validactivities = FALSE;
1039  consdata->validminact = FALSE;
1040  consdata->validmaxact = FALSE;
1041  consdata->validglbminact = FALSE;
1042  consdata->validglbmaxact = FALSE;
1043  consdata->validmaxabsval = FALSE;
1044  consdata->hasnonbinvalid = FALSE;
1045  consdata->minactivity = SCIP_INVALID;
1046  consdata->maxactivity = SCIP_INVALID;
1047  consdata->lastminactivity = SCIP_INVALID;
1048  consdata->lastmaxactivity = SCIP_INVALID;
1049  consdata->maxabsval = SCIP_INVALID;
1050  consdata->maxactdelta = SCIP_INVALID;
1051  consdata->maxactdeltavar = NULL;
1052  consdata->minactivityneginf = -1;
1053  consdata->minactivityposinf = -1;
1054  consdata->maxactivityneginf = -1;
1055  consdata->maxactivityposinf = -1;
1056  consdata->minactivityneghuge = -1;
1057  consdata->minactivityposhuge = -1;
1058  consdata->maxactivityneghuge = -1;
1059  consdata->maxactivityposhuge = -1;
1060  consdata->glbminactivity = SCIP_INVALID;
1061  consdata->glbmaxactivity = SCIP_INVALID;
1062  consdata->lastglbminactivity = SCIP_INVALID;
1063  consdata->lastglbmaxactivity = SCIP_INVALID;
1064  consdata->glbminactivityneginf = -1;
1065  consdata->glbminactivityposinf = -1;
1066  consdata->glbmaxactivityneginf = -1;
1067  consdata->glbmaxactivityposinf = -1;
1068  consdata->glbminactivityneghuge = -1;
1069  consdata->glbminactivityposhuge = -1;
1070  consdata->glbmaxactivityneghuge = -1;
1071  consdata->glbmaxactivityposhuge = -1;
1072 }
1073 
1074 /** compute the pseudo activity of a constraint */
1075 static
1077  SCIP* scip, /**< SCIP data structure */
1078  SCIP_CONSDATA* consdata /**< linear constraint data */
1079  )
1080 {
1081  int i;
1082  int pseudoactivityposinf;
1083  int pseudoactivityneginf;
1084  SCIP_Real pseudoactivity;
1085  SCIP_Real bound;
1086  SCIP_Real val;
1087 
1088  pseudoactivity = 0;
1089  pseudoactivityposinf = 0;
1090  pseudoactivityneginf = 0;
1091 
1092  for( i = consdata->nvars - 1; i >= 0; --i )
1093  {
1094  val = consdata->vals[i];
1095  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1096  if( SCIPisInfinity(scip, bound) )
1097  {
1098  if( val > 0.0 )
1099  pseudoactivityposinf++;
1100  else
1101  pseudoactivityneginf++;
1102  }
1103  else
1104  {
1105  if( SCIPisInfinity(scip, -bound) )
1106  {
1107  if( val > 0.0 )
1108  pseudoactivityneginf++;
1109  else
1110  pseudoactivityposinf++;
1111  }
1112  else
1113  pseudoactivity += val * bound;
1114  }
1115  }
1116 
1117  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1118  return SCIP_INVALID;
1119  else if( pseudoactivityneginf > 0 )
1120  return -SCIPinfinity(scip);
1121  else if( pseudoactivityposinf > 0 )
1122  return SCIPinfinity(scip);
1123 
1124  return pseudoactivity;
1125 }
1126 
1127 /** recompute the minactivity of a constraint */
1128 static
1130  SCIP* scip, /**< SCIP data structure */
1131  SCIP_CONSDATA* consdata /**< linear constraint data */
1132  )
1133 {
1134  int i;
1135  SCIP_Real bound;
1136 
1137  consdata->minactivity = 0;
1138 
1139  for( i = consdata->nvars - 1; i >= 0; --i )
1140  {
1141  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1142  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1143  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1144  consdata->minactivity += consdata->vals[i] * bound;
1145  }
1146 
1147  /* the activity was just computed from scratch and is valid now */
1148  consdata->validminact = TRUE;
1149 
1150  /* the activity was just computed from scratch, mark it to be reliable */
1151  consdata->lastminactivity = consdata->minactivity;
1152 }
1153 
1154 /** recompute the maxactivity of a constraint */
1155 static
1157  SCIP* scip, /**< SCIP data structure */
1158  SCIP_CONSDATA* consdata /**< linear constraint data */
1159  )
1160 {
1161  int i;
1162  SCIP_Real bound;
1163 
1164  consdata->maxactivity = 0;
1165 
1166  for( i = consdata->nvars - 1; i >= 0; --i )
1167  {
1168  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1169  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1170  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1171  consdata->maxactivity += consdata->vals[i] * bound;
1172  }
1173 
1174  /* the activity was just computed from scratch and is valid now */
1175  consdata->validmaxact = TRUE;
1176 
1177  /* the activity was just computed from scratch, mark it to be reliable */
1178  consdata->lastmaxactivity = consdata->maxactivity;
1179 }
1180 
1181 /** recompute the global minactivity of a constraint */
1182 static
1184  SCIP* scip, /**< SCIP data structure */
1185  SCIP_CONSDATA* consdata /**< linear constraint data */
1186  )
1187 {
1188  int i;
1189  SCIP_Real bound;
1190 
1191  consdata->glbminactivity = 0;
1192 
1193  for( i = consdata->nvars - 1; i >= 0; --i )
1194  {
1195  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1196  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1197  consdata->glbminactivity += consdata->vals[i] * bound;
1198  }
1199 
1200  /* the activity was just computed from scratch and is valid now */
1201  consdata->validglbminact = TRUE;
1202 
1203  /* the activity was just computed from scratch, mark it to be reliable */
1204  consdata->lastglbminactivity = consdata->glbminactivity;
1205 }
1206 
1207 /** recompute the global maxactivity of a constraint */
1208 static
1210  SCIP* scip, /**< SCIP data structure */
1211  SCIP_CONSDATA* consdata /**< linear constraint data */
1212  )
1213 {
1214  int i;
1215  SCIP_Real bound;
1216 
1217  consdata->glbmaxactivity = 0;
1218 
1219  for( i = consdata->nvars - 1; i >= 0; --i )
1220  {
1221  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1222  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1223  consdata->glbmaxactivity += consdata->vals[i] * bound;
1224  }
1225 
1226  /* the activity was just computed from scratch and is valid now */
1227  consdata->validglbmaxact = TRUE;
1228 
1229  /* the activity was just computed from scratch, mark it to be reliable */
1230  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1231 }
1232 
1233 /** calculates maximum absolute value of coefficients */
1234 static
1236  SCIP_CONSDATA* consdata /**< linear constraint data */
1237  )
1238 {
1239  SCIP_Real absval;
1240  int i;
1241 
1242  assert(consdata != NULL);
1243  assert(!consdata->validmaxabsval);
1244  assert(consdata->maxabsval >= SCIP_INVALID);
1245 
1246  consdata->validmaxabsval = TRUE;
1247  consdata->maxabsval = 0.0;
1248  for( i = 0; i < consdata->nvars; ++i )
1249  {
1250  absval = consdata->vals[i];
1251  absval = REALABS(absval);
1252  if( absval > consdata->maxabsval )
1253  consdata->maxabsval = absval;
1254  }
1255 }
1256 
1257 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1258 static
1260  SCIP_CONSDATA* consdata /**< linear constraint data */
1261  )
1262 {
1263  int v;
1264 
1265  assert(!consdata->hasnonbinvalid);
1266  consdata->hasnonbinvar = FALSE;
1267  consdata->hascontvar = FALSE;
1268 
1269  for( v = consdata->nvars - 1; v >= 0; --v )
1270  {
1271  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1272 
1273  if( vartype != SCIP_VARTYPE_BINARY )
1274  {
1275  consdata->hasnonbinvar = TRUE;
1276 
1277  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1278  {
1279  consdata->hascontvar = TRUE;
1280  break;
1281  }
1282  }
1283  }
1284  assert(consdata->hascontvar || v < 0);
1285 
1286  consdata->hasnonbinvalid = TRUE;
1287 }
1288 
1289 
1290 #ifdef CHECKMAXACTDELTA
1291 /* checks that the stored maximal activity delta (if not invalid) is correct */
1292 static
1294  SCIP* scip, /**< SCIP data structure */
1295  SCIP_CONSDATA* consdata /**< linear constraint data */
1296  )
1297 {
1298  if( consdata->maxactdelta != SCIP_INVALID )
1299  {
1300  SCIP_Real maxactdelta = 0.0;
1301  SCIP_Real domain;
1302  SCIP_Real delta;
1303  SCIP_Real lb;
1304  SCIP_Real ub;
1305  int v;
1306 
1307  for( v = consdata->nvars - 1; v >= 0; --v )
1308  {
1309  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1310  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1311 
1312  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1313  {
1314  maxactdelta = SCIPinfinity(scip);
1315  break;
1316  }
1317 
1318  domain = ub - lb;
1319  delta = REALABS(consdata->vals[v]) * domain;
1320 
1321  if( delta > maxactdelta )
1322  {
1323  maxactdelta = delta;
1324  }
1325  }
1326  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1327  }
1328 }
1329 #else
1330 #define checkMaxActivityDelta(scip, consdata) /**/
1331 #endif
1332 
1333 /** recompute maximal activity contribution for a single variable */
1334 static
1336  SCIP* scip, /**< SCIP data structure */
1337  SCIP_CONSDATA* consdata /**< linear constraint data */
1338  )
1339 {
1340  SCIP_Real delta;
1341  int v;
1342 
1343  consdata->maxactdelta = 0.0;
1345  if( !consdata->hasnonbinvalid )
1346  consdataCheckNonbinvar(consdata);
1347 
1348  /* easy case, the problem consists only of binary variables */
1349  if( !consdata->hasnonbinvar )
1350  {
1351  for( v = consdata->nvars - 1; v >= 0; --v )
1352  {
1353  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1354  {
1355  delta = REALABS(consdata->vals[v]);
1356 
1357  if( delta > consdata->maxactdelta )
1358  {
1359  consdata->maxactdelta = delta;
1360  consdata->maxactdeltavar = consdata->vars[v];
1361  }
1362  }
1363  }
1364  return;
1365  }
1366 
1367  for( v = consdata->nvars - 1; v >= 0; --v )
1368  {
1369  SCIP_Real domain;
1370  SCIP_Real lb;
1371  SCIP_Real ub;
1372 
1373  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1374  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1375 
1376  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1377  {
1378  consdata->maxactdelta = SCIPinfinity(scip);
1379  consdata->maxactdeltavar = consdata->vars[v];
1380  break;
1381  }
1382 
1383  domain = ub - lb;
1384  delta = REALABS(consdata->vals[v]) * domain;
1385 
1386  if( delta > consdata->maxactdelta )
1387  {
1388  consdata->maxactdelta = delta;
1389  consdata->maxactdeltavar = consdata->vars[v];
1390  }
1391  }
1392 }
1393 
1394 
1395 /** updates activities for a change in a bound */
1396 static
1398  SCIP* scip, /**< SCIP data structure */
1399  SCIP_CONSDATA* consdata, /**< linear constraint data */
1400  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1401  SCIP_Real oldbound, /**< old bound of variable */
1402  SCIP_Real newbound, /**< new bound of variable */
1403  SCIP_Real val, /**< coefficient of constraint entry */
1404  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1405  SCIP_Bool global, /**< is it a global or a local bound change? */
1406  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1407  )
1408 {
1409  SCIP_Real* activity;
1410  SCIP_Real* lastactivity;
1411  int* activityposinf;
1412  int* activityneginf;
1413  int* activityposhuge;
1414  int* activityneghuge;
1415  SCIP_Real delta;
1416  SCIP_Bool validact;
1417 
1418  assert(scip != NULL);
1419  assert(consdata != NULL);
1420  assert(global || (var != NULL));
1421  assert(consdata->validactivities);
1422  assert(consdata->minactivity < SCIP_INVALID);
1423  assert(consdata->maxactivity < SCIP_INVALID);
1424  assert(consdata->lastminactivity < SCIP_INVALID);
1425  assert(consdata->lastmaxactivity < SCIP_INVALID);
1426  assert(consdata->minactivityneginf >= 0);
1427  assert(consdata->minactivityposinf >= 0);
1428  assert(consdata->maxactivityneginf >= 0);
1429  assert(consdata->maxactivityposinf >= 0);
1430  assert(consdata->minactivityneghuge >= 0);
1431  assert(consdata->minactivityposhuge >= 0);
1432  assert(consdata->maxactivityneghuge >= 0);
1433  assert(consdata->maxactivityposhuge >= 0);
1434  assert(consdata->glbminactivity < SCIP_INVALID);
1435  assert(consdata->glbmaxactivity < SCIP_INVALID);
1436  assert(consdata->lastglbminactivity < SCIP_INVALID);
1437  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1438  assert(consdata->glbminactivityneginf >= 0);
1439  assert(consdata->glbminactivityposinf >= 0);
1440  assert(consdata->glbmaxactivityneginf >= 0);
1441  assert(consdata->glbmaxactivityposinf >= 0);
1442  assert(consdata->glbminactivityneghuge >= 0);
1443  assert(consdata->glbminactivityposhuge >= 0);
1444  assert(consdata->glbmaxactivityneghuge >= 0);
1445  assert(consdata->glbmaxactivityposhuge >= 0);
1446 
1447  delta = 0.0;
1448 
1449  /* we are updating global activities */
1450  if( global )
1451  {
1452  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1453  * lower bound + pos. coef: update minactivity
1454  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1455  * upper bound + pos. coef: update maxactivity
1456  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1457  */
1458  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1459  {
1460  if( val > 0.0 )
1461  {
1462  activity = &(consdata->glbminactivity);
1463  lastactivity = &(consdata->lastglbminactivity);
1464  activityposinf = &(consdata->glbminactivityposinf);
1465  activityneginf = &(consdata->glbminactivityneginf);
1466  activityposhuge = &(consdata->glbminactivityposhuge);
1467  activityneghuge = &(consdata->glbminactivityneghuge);
1468  validact = consdata->validglbminact;
1469  }
1470  else
1471  {
1472  activity = &(consdata->glbmaxactivity);
1473  lastactivity = &(consdata->lastglbmaxactivity);
1474  activityposinf = &(consdata->glbmaxactivityneginf);
1475  activityneginf = &(consdata->glbmaxactivityposinf);
1476  activityposhuge = &(consdata->glbmaxactivityposhuge);
1477  activityneghuge = &(consdata->glbmaxactivityneghuge);
1478  validact = consdata->validglbmaxact;
1479  }
1480  }
1481  else
1482  {
1483  if( val > 0.0 )
1484  {
1485  activity = &(consdata->glbmaxactivity);
1486  lastactivity = &(consdata->lastglbmaxactivity);
1487  activityposinf = &(consdata->glbmaxactivityposinf);
1488  activityneginf = &(consdata->glbmaxactivityneginf);
1489  activityposhuge = &(consdata->glbmaxactivityposhuge);
1490  activityneghuge = &(consdata->glbmaxactivityneghuge);
1491  validact = consdata->validglbmaxact;
1492  }
1493  else
1494  {
1495  activity = &(consdata->glbminactivity);
1496  lastactivity = &(consdata->lastglbminactivity);
1497  activityposinf = &(consdata->glbminactivityneginf);
1498  activityneginf = &(consdata->glbminactivityposinf);
1499  activityposhuge = &(consdata->glbminactivityposhuge);
1500  activityneghuge = &(consdata->glbminactivityneghuge);
1501  validact = consdata->validglbminact;
1502  }
1503  }
1504  }
1505  /* we are updating local activities */
1506  else
1507  {
1508  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1509  * lower bound + pos. coef: update minactivity
1510  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1511  * upper bound + pos. coef: update maxactivity
1512  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1513  */
1514  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1515  {
1516  if( val > 0.0 )
1517  {
1518  activity = &(consdata->minactivity);
1519  lastactivity = &(consdata->lastminactivity);
1520  activityposinf = &(consdata->minactivityposinf);
1521  activityneginf = &(consdata->minactivityneginf);
1522  activityposhuge = &(consdata->minactivityposhuge);
1523  activityneghuge = &(consdata->minactivityneghuge);
1524  validact = consdata->validminact;
1525  }
1526  else
1527  {
1528  activity = &(consdata->maxactivity);
1529  lastactivity = &(consdata->lastmaxactivity);
1530  activityposinf = &(consdata->maxactivityneginf);
1531  activityneginf = &(consdata->maxactivityposinf);
1532  activityposhuge = &(consdata->maxactivityposhuge);
1533  activityneghuge = &(consdata->maxactivityneghuge);
1534  validact = consdata->validmaxact;
1535  }
1536  }
1537  else
1538  {
1539  if( val > 0.0 )
1540  {
1541  activity = &(consdata->maxactivity);
1542  lastactivity = &(consdata->lastmaxactivity);
1543  activityposinf = &(consdata->maxactivityposinf);
1544  activityneginf = &(consdata->maxactivityneginf);
1545  activityposhuge = &(consdata->maxactivityposhuge);
1546  activityneghuge = &(consdata->maxactivityneghuge);
1547  validact = consdata->validmaxact;
1548  }
1549  else
1550  {
1551  activity = &(consdata->minactivity);
1552  lastactivity = &(consdata->lastminactivity);
1553  activityposinf = &(consdata->minactivityneginf);
1554  activityneginf = &(consdata->minactivityposinf);
1555  activityposhuge = &(consdata->minactivityposhuge);
1556  activityneghuge = &(consdata->minactivityneghuge);
1557  validact = consdata->validminact;
1558  }
1559  }
1560  }
1561 
1562  /* old bound was +infinity */
1563  if( SCIPisInfinity(scip, oldbound) )
1564  {
1565  assert((*activityposinf) >= 1);
1566 
1567  /* we only have to do something if the new bound is not again +infinity */
1568  if( !SCIPisInfinity(scip, newbound) )
1569  {
1570  /* decrease the counter for positive infinite contributions */
1571  (*activityposinf)--;
1572 
1573  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1574  if( SCIPisInfinity(scip, -newbound) )
1575  (*activityneginf)++;
1576  /* if the contribution of this variable is too large, increase the counter for huge values */
1577  else if( SCIPisHugeValue(scip, val * newbound) )
1578  {
1579  (*activityposhuge)++;
1580  }
1581  else if( SCIPisHugeValue(scip, -val * newbound) )
1582  {
1583  (*activityneghuge)++;
1584  }
1585  /* "normal case": just add the contribution to the activity */
1586  else
1587  delta = val * newbound;
1588  }
1589  }
1590  /* old bound was -infinity */
1591  else if( SCIPisInfinity(scip, -oldbound) )
1592  {
1593  assert((*activityneginf) >= 1);
1594 
1595  /* we only have to do something ig the new bound is not again -infinity */
1596  if( !SCIPisInfinity(scip, -newbound) )
1597  {
1598  /* decrease the counter for negative infinite contributions */
1599  (*activityneginf)--;
1600 
1601  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1602  if( SCIPisInfinity(scip, newbound) )
1603  (*activityposinf)++;
1604  /* if the contribution of this variable is too large, increase the counter for huge values */
1605  else if( SCIPisHugeValue(scip, val * newbound) )
1606  {
1607  (*activityposhuge)++;
1608  }
1609  else if( SCIPisHugeValue(scip, -val * newbound) )
1610  {
1611  (*activityneghuge)++;
1612  }
1613  /* "normal case": just add the contribution to the activity */
1614  else
1615  delta = val * newbound;
1616  }
1617  }
1618  /* old contribution was too large and positive */
1619  else if( SCIPisHugeValue(scip, val * oldbound) )
1620  {
1621  assert((*activityposhuge) >= 1);
1622 
1623  /* decrease the counter for huge positive contributions; it might be increased again later,
1624  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1625  */
1626  (*activityposhuge)--;
1627 
1628  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1629  if( SCIPisInfinity(scip, newbound) )
1630  (*activityposinf)++;
1631  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1632  else if( SCIPisInfinity(scip, -newbound) )
1633  (*activityneginf)++;
1634  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1635  else if( SCIPisHugeValue(scip, val * newbound) )
1636  {
1637  (*activityposhuge)++;
1638  }
1639  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1640  else if( SCIPisHugeValue(scip, -val * newbound) )
1641  {
1642  (*activityneghuge)++;
1643  }
1644  /* "normal case": just add the contribution to the activity */
1645  else
1646  delta = val * newbound;
1647  }
1648  /* old contribution was too large and negative */
1649  else if( SCIPisHugeValue(scip, -val * oldbound) )
1650  {
1651  assert((*activityneghuge) >= 1);
1652 
1653  /* decrease the counter for huge negative contributions; it might be increased again later,
1654  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1655  */
1656  (*activityneghuge)--;
1657 
1658  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1659  if( SCIPisInfinity(scip, newbound) )
1660  (*activityposinf)++;
1661  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1662  else if( SCIPisInfinity(scip, -newbound) )
1663  (*activityneginf)++;
1664  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1665  else if( SCIPisHugeValue(scip, val * newbound) )
1666  {
1667  (*activityposhuge)++;
1668  }
1669  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1670  else if( SCIPisHugeValue(scip, -val * newbound) )
1671  {
1672  (*activityneghuge)++;
1673  }
1674  /* "normal case": just add the contribution to the activity */
1675  else
1676  delta = val * newbound;
1677  }
1678  /* old bound was finite and not too large */
1679  else
1680  {
1681  /* if the new bound is +infinity, the old contribution has to be subtracted
1682  * and the counter for positive infinite contributions has to be increased
1683  */
1684  if( SCIPisInfinity(scip, newbound) )
1685  {
1686  (*activityposinf)++;
1687  delta = -val * oldbound;
1688  }
1689  /* if the new bound is -infinity, the old contribution has to be subtracted
1690  * and the counter for negative infinite contributions has to be increased
1691  */
1692  else if( SCIPisInfinity(scip, -newbound) )
1693  {
1694  (*activityneginf)++;
1695  delta = -val * oldbound;
1696  }
1697  /* if the contribution of this variable is too large, increase the counter for huge values */
1698  else if( SCIPisHugeValue(scip, val * newbound) )
1699  {
1700  (*activityposhuge)++;
1701  delta = -val * oldbound;
1702  }
1703  else if( SCIPisHugeValue(scip, -val * newbound) )
1704  {
1705  (*activityneghuge)++;
1706  delta = -val * oldbound;
1707  }
1708  /* "normal case": just update the activity */
1709  else
1710  delta = val * (newbound - oldbound);
1711  }
1712 
1713  /* update the activity, if the current value is valid and there was a change in the finite part */
1714  if( validact && (delta != 0.0) )
1715  {
1716  /* if the absolute value of the activity is increased, this is regarded as reliable,
1717  * otherwise, we check whether we can still trust the updated value
1718  */
1719  (*activity) = (*activity) + delta;
1720  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1721 
1722  if( REALABS((*lastactivity)) < REALABS(*activity) )
1723  {
1724  (*lastactivity) = (*activity);
1725  }
1726  else
1727  {
1728  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1729  {
1730  SCIPdebugMessage("%s activity of linear constraint unreliable after update: %16.9g\n",
1731  (global ? "global " : ""), (*activity));
1732 
1733  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1734  if( global )
1735  {
1736  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1737  consdata->validglbminact = FALSE;
1738  else
1739  consdata->validglbmaxact = FALSE;
1740  }
1741  else
1742  {
1743  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1744  consdata->validminact = FALSE;
1745  else
1746  consdata->validmaxact = FALSE;
1747  }
1748  }
1749  }
1750  }
1751 }
1752 
1753 /** updates minimum and maximum activity for a change in lower bound */
1754 static
1756  SCIP* scip, /**< SCIP data structure */
1757  SCIP_CONSDATA* consdata, /**< linear constraint data */
1758  SCIP_VAR* var, /**< variable that has been changed */
1759  SCIP_Real oldlb, /**< old lower bound of variable */
1760  SCIP_Real newlb, /**< new lower bound of variable */
1761  SCIP_Real val, /**< coefficient of constraint entry */
1762  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1763  )
1764 {
1765  assert(scip != NULL);
1766  assert(consdata != NULL);
1767  assert(var != NULL);
1768 
1769  if( consdata->validactivities )
1770  {
1771  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1772 
1773  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1774  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1775  }
1776 }
1777 
1778 /** updates minimum and maximum activity for a change in upper bound */
1779 static
1781  SCIP* scip, /**< SCIP data structure */
1782  SCIP_CONSDATA* consdata, /**< linear constraint data */
1783  SCIP_VAR* var, /**< variable that has been changed */
1784  SCIP_Real oldub, /**< old upper bound of variable */
1785  SCIP_Real newub, /**< new upper bound of variable */
1786  SCIP_Real val, /**< coefficient of constraint entry */
1787  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1788  )
1789 {
1790  assert(scip != NULL);
1791  assert(consdata != NULL);
1792  assert(var != NULL);
1793 
1794  if( consdata->validactivities )
1795  {
1796  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
1797 
1798  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1799  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1800  }
1801 }
1802 
1803 /** updates minimum and maximum global activity for a change in the global lower bound */
1804 static
1806  SCIP* scip, /**< SCIP data structure */
1807  SCIP_CONSDATA* consdata, /**< linear constraint data */
1808  SCIP_Real oldlb, /**< old lower bound of variable */
1809  SCIP_Real newlb, /**< new lower bound of variable */
1810  SCIP_Real val, /**< coefficient of constraint entry */
1811  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1812  )
1813 {
1814  assert(scip != NULL);
1815  assert(consdata != NULL);
1816 
1817  if( consdata->validactivities )
1818  {
1819  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
1820 
1821  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1822  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1823  }
1824 }
1825 
1826 /** updates minimum and maximum global activity for a change in global upper bound */
1827 static
1829  SCIP* scip, /**< SCIP data structure */
1830  SCIP_CONSDATA* consdata, /**< linear constraint data */
1831  SCIP_Real oldub, /**< old upper bound of variable */
1832  SCIP_Real newub, /**< new upper bound of variable */
1833  SCIP_Real val, /**< coefficient of constraint entry */
1834  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1835  )
1836 {
1837  assert(scip != NULL);
1838  assert(consdata != NULL);
1839 
1840  if( consdata->validactivities )
1841  {
1842  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
1843 
1844  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1845  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1846  }
1847 }
1848 
1849 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
1850 static
1852  SCIP* scip, /**< SCIP data structure */
1853  SCIP_CONSDATA* consdata, /**< linear constraint data */
1854  SCIP_VAR* var, /**< variable of constraint entry */
1855  SCIP_Real val, /**< coefficient of constraint entry */
1856  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1857  )
1858 {
1859  assert(scip != NULL);
1860  assert(consdata != NULL);
1861  assert(var != NULL);
1862 
1863  /* update maximum absolute value */
1864  if( consdata->validmaxabsval )
1865  {
1866  SCIP_Real absval;
1867 
1868  assert(consdata->maxabsval < SCIP_INVALID);
1869 
1870  absval = REALABS(val);
1871  consdata->maxabsval = MAX(consdata->maxabsval, absval);
1872  }
1873 
1874  /* update minimal and maximal activity */
1875  if( consdata->validactivities )
1876  {
1877  assert(consdata->minactivity < SCIP_INVALID);
1878  assert(consdata->maxactivity < SCIP_INVALID);
1879  assert(consdata->glbminactivity < SCIP_INVALID);
1880  assert(consdata->glbmaxactivity < SCIP_INVALID);
1881 
1882  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
1883  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
1884  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
1885  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
1886  }
1887 }
1888 
1889 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
1890 static
1892  SCIP* scip, /**< SCIP data structure */
1893  SCIP_CONSDATA* consdata, /**< linear constraint data */
1894  SCIP_VAR* var, /**< variable of constraint entry */
1895  SCIP_Real val, /**< coefficient of constraint entry */
1896  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1897  )
1898 {
1899  assert(scip != NULL);
1900  assert(consdata != NULL);
1901  assert(var != NULL);
1902 
1903  /* invalidate maximum absolute value, if this coefficient was the maximum */
1904  if( consdata->validmaxabsval )
1905  {
1906  SCIP_Real absval;
1907 
1908  absval = REALABS(val);
1909 
1910  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
1911  {
1912  consdata->validmaxabsval = FALSE;
1913  consdata->maxabsval = SCIP_INVALID;
1914  }
1915  }
1916 
1917  /* update minimal and maximal activity */
1918  if( consdata->validactivities )
1919  {
1920  assert(consdata->minactivity < SCIP_INVALID);
1921  assert(consdata->maxactivity < SCIP_INVALID);
1922  assert(consdata->glbminactivity < SCIP_INVALID);
1923  assert(consdata->glbmaxactivity < SCIP_INVALID);
1924 
1925  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
1926  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
1927  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
1928  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
1929  }
1930 }
1931 
1932 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
1933 static
1935  SCIP* scip, /**< SCIP data structure */
1936  SCIP_CONSDATA* consdata, /**< linear constraint data */
1937  SCIP_VAR* var, /**< variable of constraint entry */
1938  SCIP_Real oldval, /**< old coefficient of constraint entry */
1939  SCIP_Real newval, /**< new coefficient of constraint entry */
1940  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1941  )
1942 {
1943  assert(scip != NULL);
1944  assert(consdata != NULL);
1945  assert(var != NULL);
1946 
1947  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
1948  assert(!SCIPisZero(scip, oldval));
1949 
1950  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
1951  assert(!SCIPisZero(scip, newval));
1952 
1953  /* update maximum absolute value */
1954  if( consdata->validmaxabsval )
1955  {
1956  SCIP_Real absval;
1957 
1958  absval = REALABS(newval);
1959 
1960  if( SCIPisGE(scip, absval, consdata->maxabsval) )
1961  {
1962  consdata->maxabsval = absval;
1963  }
1964  else
1965  {
1966  absval = REALABS(oldval);
1967 
1968  /* invalidate maximum absolute value */
1969  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
1970  {
1971  consdata->validmaxabsval = FALSE;
1972  consdata->maxabsval = SCIP_INVALID;
1973  }
1974  }
1975  }
1976 
1977  /* update maximum activity delta */
1978  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
1979  {
1980  SCIP_Real domain;
1981  SCIP_Real delta;
1982 
1983  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
1984  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
1985 
1986  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
1987  delta = REALABS(newval) * domain;
1988 
1989  if( delta > consdata->maxactdelta )
1990  {
1991  consdata->maxactdelta = delta;
1992  consdata->maxactdeltavar = var;
1993  }
1994  else
1995  {
1996  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
1997  if( consdata->maxactdeltavar == var )
1998  consdata->maxactdelta = SCIP_INVALID;
1999  }
2000  }
2001 
2002  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2003  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2004  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2005 }
2006 
2007 /** returns the maximum absolute value of all coefficients in the constraint */
2008 static
2010  SCIP_CONSDATA* consdata /**< linear constraint data */
2011  )
2012 {
2013  assert(consdata != NULL);
2014 
2015  if( !consdata->validmaxabsval )
2016  consdataCalcMaxAbsval(consdata);
2017  assert(consdata->validmaxabsval);
2018  assert(consdata->maxabsval < SCIP_INVALID);
2019 
2020  return consdata->maxabsval;
2021 }
2022 
2023 /** calculates minimum and maximum local and global activity for constraint from scratch;
2024  * additionally recalculates maximum absolute value of coefficients
2025  */
2026 static
2028  SCIP* scip, /**< SCIP data structure */
2029  SCIP_CONSDATA* consdata /**< linear constraint data */
2030  )
2031 {
2032  int i;
2033 
2034  assert(scip != NULL);
2035  assert(consdata != NULL);
2036  assert(!consdata->validactivities);
2037  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2038  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2039  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2040  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2042  consdata->validmaxabsval = TRUE;
2043  consdata->validactivities = TRUE;
2044  consdata->validminact = TRUE;
2045  consdata->validmaxact = TRUE;
2046  consdata->validglbminact = TRUE;
2047  consdata->validglbmaxact = TRUE;
2048  consdata->maxabsval = 0.0;
2049  consdata->minactivity = 0.0;
2050  consdata->maxactivity = 0.0;
2051  consdata->lastminactivity = 0.0;
2052  consdata->lastmaxactivity = 0.0;
2053  consdata->minactivityneginf = 0;
2054  consdata->minactivityposinf = 0;
2055  consdata->maxactivityneginf = 0;
2056  consdata->maxactivityposinf = 0;
2057  consdata->minactivityneghuge = 0;
2058  consdata->minactivityposhuge = 0;
2059  consdata->maxactivityneghuge = 0;
2060  consdata->maxactivityposhuge = 0;
2061  consdata->glbminactivity = 0.0;
2062  consdata->glbmaxactivity = 0.0;
2063  consdata->lastglbminactivity = 0.0;
2064  consdata->lastglbmaxactivity = 0.0;
2065  consdata->glbminactivityneginf = 0;
2066  consdata->glbminactivityposinf = 0;
2067  consdata->glbmaxactivityneginf = 0;
2068  consdata->glbmaxactivityposinf = 0;
2069  consdata->glbminactivityneghuge = 0;
2070  consdata->glbminactivityposhuge = 0;
2071  consdata->glbmaxactivityneghuge = 0;
2072  consdata->glbmaxactivityposhuge = 0;
2073 
2074  for( i = 0; i < consdata->nvars; ++i )
2075  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2076 
2077  consdata->lastminactivity = consdata->minactivity;
2078  consdata->lastmaxactivity = consdata->maxactivity;
2079  consdata->lastglbminactivity = consdata->glbminactivity;
2080  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2081 }
2082 
2083 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2084  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2085  */
2086 static
2087 void getMinActivity(
2088  SCIP* scip, /**< SCIP data structure */
2089  SCIP_CONSDATA* consdata, /**< linear constraint */
2090  int posinf, /**< number of coefficients contributing pos. infinite value */
2091  int neginf, /**< number of coefficients contributing neg. infinite value */
2092  int poshuge, /**< number of coefficients contributing huge pos. value */
2093  int neghuge, /**< number of coefficients contributing huge neg. value */
2094  SCIP_Real delta, /**< value to subtract from stored minactivity
2095  * (contribution of the variable set to zero when getting residual activity) */
2096  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2097  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2098  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2099  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2100  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2101  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2102  )
2103 {
2104  assert(scip != NULL);
2105  assert(consdata != NULL);
2106  assert(posinf >= 0);
2107  assert(neginf >= 0);
2108  assert(poshuge >= 0);
2109  assert(neghuge >= 0);
2110  assert(minactivity != NULL);
2111  assert(isrelax != NULL);
2112  assert(issettoinfinity != NULL);
2113 
2114  /* if we have pos. infinite contributions, the minactivity is +infty */
2115  if( posinf > 0 )
2116  {
2117  *minactivity = SCIPinfinity(scip);
2118  *issettoinfinity = TRUE;
2119  *isrelax = FALSE;
2120  }
2121  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2122  else if( neginf > 0 )
2123  {
2124  *minactivity = -SCIPinfinity(scip);
2125  *issettoinfinity = TRUE;
2126  *isrelax = FALSE;
2127  }
2128  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2129  else if( neghuge > 0 )
2130  {
2131  *minactivity = -SCIPinfinity(scip);
2132  *issettoinfinity = TRUE;
2133  *isrelax = TRUE;
2134  }
2135  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2136  else if( !goodrelax && poshuge > 0 )
2137  {
2138  *minactivity = -SCIPinfinity(scip);
2139  *issettoinfinity = TRUE;
2140  *isrelax = TRUE;
2141  }
2142  else
2143  {
2144  SCIP_Real tmpactivity;
2145 
2146  /* recompute minactivity if it is not valid */
2147  if( global )
2148  {
2149  if( !consdata->validglbminact )
2150  consdataRecomputeGlbMinactivity(scip, consdata);
2151  assert(consdata->validglbminact);
2152 
2153  tmpactivity = consdata->glbminactivity;
2154  }
2155  else
2156  {
2157  if( !consdata->validminact )
2158  consdataRecomputeMinactivity(scip, consdata);
2159  assert(consdata->validminact);
2160 
2161  tmpactivity = consdata->minactivity;
2162  }
2163 
2164  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2165  * a feasible relaxation of the minactivity is the number of positive huge contributions
2166  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2167  */
2168  if( poshuge > 0 )
2169  {
2170  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2171  *issettoinfinity = FALSE;
2172  *isrelax = TRUE;
2173  }
2174  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2175  else
2176  {
2177  *minactivity = tmpactivity - delta;
2178  *issettoinfinity = FALSE;
2179  *isrelax = FALSE;
2180  }
2181  }
2182 }
2183 
2184 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2185  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2186  */
2187 static
2188 void getMaxActivity(
2189  SCIP* scip, /**< SCIP data structure */
2190  SCIP_CONSDATA* consdata, /**< linear constraint */
2191  int posinf, /**< number of coefficients contributing pos. infinite value */
2192  int neginf, /**< number of coefficients contributing neg. infinite value */
2193  int poshuge, /**< number of coefficients contributing huge pos. value */
2194  int neghuge, /**< number of coefficients contributing huge neg. value */
2195  SCIP_Real delta, /**< value to subtract from stored maxactivity
2196  * (contribution of the variable set to zero when getting residual activity) */
2197  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2198  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2199  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2200  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2201  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2202  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2203  )
2204 {
2205  assert(scip != NULL);
2206  assert(consdata != NULL);
2207  assert(posinf >= 0);
2208  assert(neginf >= 0);
2209  assert(poshuge >= 0);
2210  assert(neghuge >= 0);
2211  assert(maxactivity != NULL);
2212  assert(isrelax != NULL);
2213  assert(issettoinfinity != NULL);
2214 
2215  /* if we have neg. infinite contributions, the maxactivity is -infty */
2216  if( neginf > 0 )
2217  {
2218  *maxactivity = -SCIPinfinity(scip);
2219  *issettoinfinity = TRUE;
2220  *isrelax = FALSE;
2221  }
2222  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2223  else if( posinf > 0 )
2224  {
2225  *maxactivity = SCIPinfinity(scip);
2226  *issettoinfinity = TRUE;
2227  *isrelax = FALSE;
2228  }
2229  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2230  else if( poshuge > 0 )
2231  {
2232  *maxactivity = SCIPinfinity(scip);
2233  *issettoinfinity = TRUE;
2234  *isrelax = TRUE;
2235  }
2236  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2237  else if( !goodrelax && neghuge > 0 )
2238  {
2239  *maxactivity = SCIPinfinity(scip);
2240  *issettoinfinity = TRUE;
2241  *isrelax = TRUE;
2242  }
2243  else
2244  {
2245  SCIP_Real tmpactivity;
2246 
2247  /* recompute maxactivity if it is not valid */
2248  if( global )
2249  {
2250  if( !consdata->validglbmaxact )
2251  consdataRecomputeGlbMaxactivity(scip, consdata);
2252  assert(consdata->validglbmaxact);
2253 
2254  tmpactivity = consdata->glbmaxactivity;
2255  }
2256  else
2257  {
2258  if( !consdata->validmaxact )
2259  consdataRecomputeMaxactivity(scip, consdata);
2260  assert(consdata->validmaxact);
2261 
2262  tmpactivity = consdata->maxactivity;
2263  }
2264 
2265  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2266  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2267  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2268  */
2269  if( neghuge > 0 )
2270  {
2271  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2272  *issettoinfinity = FALSE;
2273  *isrelax = TRUE;
2274  }
2275  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2276  else
2277  {
2278  *maxactivity = tmpactivity - delta;
2279  *issettoinfinity = FALSE;
2280  *isrelax = FALSE;
2281  }
2282  }
2283 }
2284 
2285 /** gets activity bounds for constraint */
2286 static
2288  SCIP* scip, /**< SCIP data structure */
2289  SCIP_CONSDATA* consdata, /**< linear constraint */
2290  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2291  * relaxed acticities ignored, anyway? */
2292  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2293  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2294  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2295  * i.e. <= the exact minactivity (in case of huge contributions),
2296  * or equal to the exact minimal activity */
2297  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2298  * i.e. >= the exact maxactivity (in case of huge contributions),
2299  * or equal to the exact maximal activity */
2300  )
2302  SCIP_Bool issettoinfinity;
2303 
2304  assert(scip != NULL);
2305  assert(consdata != NULL);
2306  assert(minactivity != NULL);
2307  assert(maxactivity != NULL);
2308 
2309  if( !consdata->validactivities )
2310  {
2311  consdataCalcActivities(scip, consdata);
2312  assert(consdata->validminact);
2313  assert(consdata->validmaxact);
2314  }
2315  assert(consdata->minactivity < SCIP_INVALID);
2316  assert(consdata->maxactivity < SCIP_INVALID);
2317  assert(consdata->minactivityneginf >= 0);
2318  assert(consdata->minactivityposinf >= 0);
2319  assert(consdata->maxactivityneginf >= 0);
2320  assert(consdata->maxactivityposinf >= 0);
2321 
2322  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2323  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2324  minactivity, minisrelax, &issettoinfinity);
2325 
2326  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2327  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2328  maxactivity, maxisrelax, &issettoinfinity);
2329 }
2330 
2331 /** calculates activity bounds for constraint after setting variable to zero */
2332 static
2334  SCIP* scip, /**< SCIP data structure */
2335  SCIP_CONSDATA* consdata, /**< linear constraint */
2336  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2337  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2338  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2339  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2340  )
2341 {
2342  SCIP_VAR* var;
2343  SCIP_Real val;
2344  SCIP_Real lb;
2345  SCIP_Real ub;
2346  int v;
2348  assert(scip != NULL);
2349  assert(consdata != NULL);
2350  assert(cancelvar != NULL);
2351  assert(resactivity != NULL);
2352 
2353  *resactivity = 0.0;
2354 
2355  for( v = 0; v < consdata->nvars; ++v )
2356  {
2357  var = consdata->vars[v];
2358  assert(var != NULL);
2359  if( var == cancelvar )
2360  continue;
2361 
2362  val = consdata->vals[v];
2363 
2364  if( useglobalbounds )
2365  {
2366  lb = SCIPvarGetLbGlobal(var);
2367  ub = SCIPvarGetUbGlobal(var);
2368  }
2369  else
2370  {
2371  lb = SCIPvarGetLbLocal(var);
2372  ub = SCIPvarGetUbLocal(var);
2373  }
2374 
2375  assert(!SCIPisZero(scip, val));
2376  assert(SCIPisLE(scip, lb, ub));
2377 
2378  if( val > 0.0 )
2379  {
2380  if( isminresact )
2381  {
2382  assert(!SCIPisInfinity(scip, -lb));
2383  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2384  *resactivity += val*lb;
2385  }
2386  else
2387  {
2388  assert(!SCIPisInfinity(scip, ub));
2389  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2390  *resactivity += val*ub;
2391  }
2392  }
2393  else
2394  {
2395  if( isminresact)
2396  {
2397  assert(!SCIPisInfinity(scip, ub));
2398  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2399  *resactivity += val*ub;
2400  }
2401  else
2402  {
2403  assert(!SCIPisInfinity(scip, -lb));
2404  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2405  *resactivity += val*lb;
2406  }
2407  }
2408  }
2409  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2410 }
2411 
2412 /** gets activity bounds for constraint after setting variable to zero */
2413 static
2415  SCIP* scip, /**< SCIP data structure */
2416  SCIP_CONSDATA* consdata, /**< linear constraint */
2417  SCIP_VAR* var, /**< variable to calculate activity residual for */
2418  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2419  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2420  * relaxed acticities ignored, anyway? */
2421  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2422  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2423  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2424  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2425  * contributions), or equal to the exact residual minactivity */
2426  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2427  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2428  * contributions), or equal to the exact residual minactivity */
2429  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2430  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2431  )
2432 {
2433  SCIP_Real minactbound;
2434  SCIP_Real maxactbound;
2435  SCIP_Real absval;
2436 
2437  assert(scip != NULL);
2438  assert(consdata != NULL);
2439  assert(var != NULL);
2440  assert(minresactivity != NULL);
2441  assert(maxresactivity != NULL);
2442  assert(minisrelax != NULL);
2443  assert(maxisrelax != NULL);
2444  assert(isminsettoinfinity != NULL);
2445  assert(ismaxsettoinfinity != NULL);
2446 
2447  /* get activity bounds of linear constraint */
2448  if( !consdata->validactivities )
2449  {
2450  consdataCalcActivities(scip, consdata);
2451  assert(consdata->validminact);
2452  assert(consdata->validmaxact);
2453  }
2454  assert(consdata->minactivity < SCIP_INVALID);
2455  assert(consdata->maxactivity < SCIP_INVALID);
2456  assert(consdata->minactivityneginf >= 0);
2457  assert(consdata->minactivityposinf >= 0);
2458  assert(consdata->maxactivityneginf >= 0);
2459  assert(consdata->maxactivityposinf >= 0);
2460  assert(consdata->minactivityneghuge >= 0);
2461  assert(consdata->minactivityposhuge >= 0);
2462  assert(consdata->maxactivityneghuge >= 0);
2463  assert(consdata->maxactivityposhuge >= 0);
2464 
2465  if( val > 0.0 )
2466  {
2467  minactbound = SCIPvarGetLbLocal(var);
2468  maxactbound = SCIPvarGetUbLocal(var);
2469  absval = val;
2470  }
2471  else
2472  {
2473  minactbound = -SCIPvarGetUbLocal(var);
2474  maxactbound = -SCIPvarGetLbLocal(var);
2475  absval = -val;
2476  }
2477 
2478  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2479  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2480  */
2481  if( SCIPisInfinity(scip, minactbound) )
2482  {
2483  assert(consdata->minactivityposinf >= 1);
2484 
2485  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2486  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2487  minresactivity, minisrelax, isminsettoinfinity);
2488  }
2489  else if( SCIPisInfinity(scip, -minactbound) )
2490  {
2491  assert(consdata->minactivityneginf >= 1);
2492 
2493  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2494  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2495  minresactivity, minisrelax, isminsettoinfinity);
2496  }
2497  else if( SCIPisHugeValue(scip, minactbound * absval) )
2498  {
2499  assert(consdata->minactivityposhuge >= 1);
2500 
2501  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2502  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2503  minresactivity, minisrelax, isminsettoinfinity);
2504  }
2505  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2506  {
2507  assert(consdata->minactivityneghuge >= 1);
2508 
2509  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2510  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2511  minresactivity, minisrelax, isminsettoinfinity);
2512  }
2513  else
2514  {
2515  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2516  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2517  minresactivity, minisrelax, isminsettoinfinity);
2518  }
2519 
2520  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2521  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2522  */
2523  if( SCIPisInfinity(scip, -maxactbound) )
2524  {
2525  assert(consdata->maxactivityneginf >= 1);
2526 
2527  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2528  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2529  maxresactivity, maxisrelax, ismaxsettoinfinity);
2530  }
2531  else if( SCIPisInfinity(scip, maxactbound) )
2532  {
2533  assert(consdata->maxactivityposinf >= 1);
2534 
2535  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2536  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2537  maxresactivity, maxisrelax, ismaxsettoinfinity);
2538  }
2539  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2540  {
2541  assert(consdata->maxactivityposhuge >= 1);
2542 
2543  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2544  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2545  maxresactivity, maxisrelax, ismaxsettoinfinity);
2546  }
2547  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2548  {
2549  assert(consdata->maxactivityneghuge >= 1);
2550 
2551  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2552  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2553  maxresactivity, maxisrelax, ismaxsettoinfinity);
2554  }
2555  else
2556  {
2557  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2558  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2559  maxresactivity, maxisrelax, ismaxsettoinfinity);
2560  }
2561 }
2562 
2563 /** gets global activity bounds for constraint */
2564 static
2566  SCIP* scip, /**< SCIP data structure */
2567  SCIP_CONSDATA* consdata, /**< linear constraint */
2568  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2569  * relaxed acticities ignored, anyway? */
2570  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2571  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2572  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2573  * i.e. <= the exact minactivity (in case of huge contributions),
2574  * or equal to the exact minimal activity */
2575  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2576  * i.e. >= the exact maxactivity (in case of huge contributions),
2577  * or equal to the exact maximal activity */
2578  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2579  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2580  )
2581 {
2582  assert(scip != NULL);
2583  assert(consdata != NULL);
2584  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2585  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2586 
2587  if( !consdata->validactivities )
2588  {
2589  consdataCalcActivities(scip, consdata);
2590  assert(consdata->validglbminact);
2591  assert(consdata->validglbmaxact);
2592  }
2593  assert(consdata->glbminactivity < SCIP_INVALID);
2594  assert(consdata->glbmaxactivity < SCIP_INVALID);
2595  assert(consdata->glbminactivityneginf >= 0);
2596  assert(consdata->glbminactivityposinf >= 0);
2597  assert(consdata->glbmaxactivityneginf >= 0);
2598  assert(consdata->glbmaxactivityposinf >= 0);
2599  assert(consdata->glbminactivityneghuge >= 0);
2600  assert(consdata->glbminactivityposhuge >= 0);
2601  assert(consdata->glbmaxactivityneghuge >= 0);
2602  assert(consdata->glbmaxactivityposhuge >= 0);
2603 
2604  if( glbminactivity != NULL )
2605  {
2606  assert(isminsettoinfinity != NULL);
2607  assert(minisrelax != NULL);
2608 
2609  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2610  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2611  glbminactivity, minisrelax, isminsettoinfinity);
2612  }
2613 
2614  if( glbmaxactivity != NULL )
2615  {
2616  assert(ismaxsettoinfinity != NULL);
2617  assert(maxisrelax != NULL);
2618 
2619  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2620  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2621  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2622  }
2623 }
2624 
2625 /** gets global activity bounds for constraint after setting variable to zero */
2626 static
2628  SCIP* scip, /**< SCIP data structure */
2629  SCIP_CONSDATA* consdata, /**< linear constraint */
2630  SCIP_VAR* var, /**< variable to calculate activity residual for */
2631  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2632  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2633  * relaxed acticities ignored, anyway? */
2634  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2635  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2636  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2637  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2638  * contributions), or equal to the exact residual minactivity */
2639  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2640  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2641  * contributions), or equal to the exact residual minactivity */
2642  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2643  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2644  )
2645 {
2646  SCIP_Real minactbound;
2647  SCIP_Real maxactbound;
2648  SCIP_Real absval;
2649 
2650  assert(scip != NULL);
2651  assert(consdata != NULL);
2652  assert(var != NULL);
2653  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2654  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2655 
2656  /* get activity bounds of linear constraint */
2657  if( !consdata->validactivities )
2658  consdataCalcActivities(scip, consdata);
2659 
2660  assert(consdata->glbminactivity < SCIP_INVALID);
2661  assert(consdata->glbmaxactivity < SCIP_INVALID);
2662  assert(consdata->glbminactivityneginf >= 0);
2663  assert(consdata->glbminactivityposinf >= 0);
2664  assert(consdata->glbmaxactivityneginf >= 0);
2665  assert(consdata->glbmaxactivityposinf >= 0);
2666 
2667  if( val > 0.0 )
2668  {
2669  minactbound = SCIPvarGetLbGlobal(var);
2670  maxactbound = SCIPvarGetUbGlobal(var);
2671  absval = val;
2672  }
2673  else
2674  {
2675  minactbound = -SCIPvarGetUbGlobal(var);
2676  maxactbound = -SCIPvarGetLbGlobal(var);
2677  absval = -val;
2678  }
2679 
2680  if( minresactivity != NULL )
2681  {
2682  assert(isminsettoinfinity != NULL);
2683  assert(minisrelax != NULL);
2684 
2685  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2686  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2687  */
2688  if( SCIPisInfinity(scip, minactbound) )
2689  {
2690  assert(consdata->glbminactivityposinf >= 1);
2691 
2692  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2693  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2694  minresactivity, minisrelax, isminsettoinfinity);
2695  }
2696  else if( SCIPisInfinity(scip, -minactbound) )
2697  {
2698  assert(consdata->glbminactivityneginf >= 1);
2699 
2700  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2701  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2702  minresactivity, minisrelax, isminsettoinfinity);
2703  }
2704  else if( SCIPisHugeValue(scip, minactbound * absval) )
2705  {
2706  assert(consdata->glbminactivityposhuge >= 1);
2707 
2708  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2709  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2710  minresactivity, minisrelax, isminsettoinfinity);
2711  }
2712  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2713  {
2714  assert(consdata->glbminactivityneghuge >= 1);
2715 
2716  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2717  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2718  minresactivity, minisrelax, isminsettoinfinity);
2719  }
2720  else
2721  {
2722  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2723  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2724  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
2725  }
2726  }
2727 
2728  if( maxresactivity != NULL )
2729  {
2730  assert(ismaxsettoinfinity != NULL);
2731  assert(maxisrelax != NULL);
2732 
2733  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2734  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2735  */
2736  if( SCIPisInfinity(scip, -maxactbound) )
2737  {
2738  assert(consdata->glbmaxactivityneginf >= 1);
2739 
2740  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2741  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2742  maxresactivity, maxisrelax, ismaxsettoinfinity);
2743  }
2744  else if( SCIPisInfinity(scip, maxactbound) )
2745  {
2746  assert(consdata->glbmaxactivityposinf >= 1);
2747 
2748  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2749  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2750  maxresactivity, maxisrelax, ismaxsettoinfinity);
2751  }
2752  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2753  {
2754  assert(consdata->glbmaxactivityposhuge >= 1);
2755 
2756  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2757  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2758  maxresactivity, maxisrelax, ismaxsettoinfinity);
2759  }
2760  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2761  {
2762  assert(consdata->glbmaxactivityneghuge >= 1);
2763 
2764  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2765  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
2766  maxresactivity, maxisrelax, ismaxsettoinfinity);
2767  }
2768  else
2769  {
2770  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2771  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
2772  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
2773  }
2774  }
2775 }
2776 
2777 /** calculates the activity of the linear constraint for given solution */
2778 static
2780  SCIP* scip, /**< SCIP data structure */
2781  SCIP_CONSDATA* consdata, /**< linear constraint data */
2782  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
2783  )
2784 {
2785  SCIP_Real activity;
2786 
2787  assert(scip != NULL);
2788  assert(consdata != NULL);
2789 
2790  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
2791  activity = consdataComputePseudoActivity(scip, consdata);
2792  else
2793  {
2794  SCIP_Real solval;
2795  int nposinf;
2796  int nneginf;
2797  SCIP_Bool negsign;
2798  int v;
2799 
2800  activity = 0.0;
2801  nposinf = 0;
2802  nneginf = 0;
2803  negsign = 0;
2804 
2805  for( v = 0; v < consdata->nvars; ++v )
2806  {
2807  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
2808 
2809  if( consdata->vals[v] < 0 )
2810  negsign = TRUE;
2811  else
2812  negsign = FALSE;
2813 
2814  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
2815  ++nposinf;
2816  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
2817  ++nneginf;
2818  else
2819  activity += consdata->vals[v] * solval;
2820  }
2821  assert(nneginf >= 0 && nposinf >= 0);
2822 
2823  SCIPdebugMessage("activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
2824 
2825  /* check for amount of infinity values and correct the activity */
2826  if( nposinf > 0 && nneginf > 0 )
2827  activity = (consdata->rhs + consdata->lhs) / 2;
2828  else if( nposinf > 0 )
2829  activity = SCIPinfinity(scip);
2830  else if( nneginf > 0 )
2831  activity = -SCIPinfinity(scip);
2832 
2833  SCIPdebugMessage("corrected activity of linear constraint: %.15g\n", activity);
2834  }
2835 
2836  if( activity == SCIP_INVALID ) /*lint !e777*/
2837  return activity;
2838  else if( activity < 0 )
2839  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
2840  else
2841  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
2842 
2843  return activity;
2844 }
2845 
2846 /** calculates the feasibility of the linear constraint for given solution */
2847 static
2849  SCIP* scip, /**< SCIP data structure */
2850  SCIP_CONSDATA* consdata, /**< linear constraint data */
2851  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
2852  )
2853 {
2854  SCIP_Real activity;
2855 
2856  assert(scip != NULL);
2857  assert(consdata != NULL);
2858 
2859  activity = consdataGetActivity(scip, consdata, sol);
2860 
2861  if( activity == SCIP_INVALID ) /*lint !e777*/
2862  return -SCIPinfinity(scip);
2863 
2864  return MIN(consdata->rhs - activity, activity - consdata->lhs);
2865 }
2866 
2867 /** returns the signature bitmask for the given variable */
2868 static
2870  SCIP_VAR* var /**< variable */
2871  )
2872 {
2873  int sigidx;
2874 
2875  assert(var != NULL);
2876 
2877  sigidx = SCIPvarGetIndex(var) % (int)(8*sizeof(SCIP_Longint));
2878  return ((SCIP_Longint)1) << sigidx; /*lint !e703*/
2879 }
2880 
2881 /** updates bit signatures after adding a single coefficient */
2882 static
2884  SCIP_CONSDATA* consdata, /**< linear constraint data */
2885  int pos /**< position of coefficient to update signatures for */
2886  )
2887 {
2888  SCIP_Longint varsignature;
2889  SCIP_Real lb;
2890  SCIP_Real ub;
2891  SCIP_Real val;
2892 
2893  assert(consdata != NULL);
2894  assert(consdata->validsignature);
2895 
2896  varsignature = getVarSignature(consdata->vars[pos]);
2897  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
2898  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
2899  val = consdata->vals[pos];
2900  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
2901  consdata->possignature |= varsignature;
2902  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
2903  consdata->negsignature |= varsignature;
2904 }
2905 
2906 /** calculates the bit signatures of the given constraint data */
2907 static
2909  SCIP_CONSDATA* consdata /**< linear constraint data */
2910  )
2911 {
2912  assert(consdata != NULL);
2913 
2914  if( !consdata->validsignature )
2915  {
2916  int i;
2917 
2918  consdata->validsignature = TRUE;
2919  consdata->possignature = 0;
2920  consdata->negsignature = 0;
2921  for( i = 0; i < consdata->nvars; ++i )
2923  }
2924 }
2925 
2926 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
2927 static
2928 SCIP_DECL_SORTINDCOMP(consdataCompVar)
2929 { /*lint --e{715}*/
2930  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
2931 
2932  assert(consdata != NULL);
2933  assert(0 <= ind1 && ind1 < consdata->nvars);
2934  assert(0 <= ind2 && ind2 < consdata->nvars);
2935 
2936  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
2937 }
2938 
2939 /** permutes the constraint's variables according to a given permutation. */
2940 static
2941 void permSortConsdata(
2942  SCIP_CONSDATA* consdata, /**< the constraint data */
2943  int* perm, /**< the target permutation */
2944  int nvars /**< the number of variables */
2945  )
2946 { /*lint --e{715}*/
2947  SCIP_VAR* varv;
2948  SCIP_EVENTDATA* eventdatav;
2949  SCIP_Real valv;
2950  int v;
2951  int i;
2952  int nexti;
2953 
2954  assert(perm != NULL);
2955  assert(consdata != NULL);
2956 
2957  /* permute the variables in the linear constraint according to the target permutation */
2958  eventdatav = NULL;
2959  for( v = 0; v < nvars; ++v )
2960  {
2961  if( perm[v] != v )
2962  {
2963  varv = consdata->vars[v];
2964  valv = consdata->vals[v];
2965  if( consdata->eventdata != NULL )
2966  eventdatav = consdata->eventdata[v];
2967  i = v;
2968  do
2969  {
2970  assert(0 <= perm[i] && perm[i] < nvars);
2971  assert(perm[i] != i);
2972  consdata->vars[i] = consdata->vars[perm[i]];
2973  consdata->vals[i] = consdata->vals[perm[i]];
2974  if( consdata->eventdata != NULL )
2975  {
2976  consdata->eventdata[i] = consdata->eventdata[perm[i]];
2977  consdata->eventdata[i]->varpos = i;
2978  }
2979  nexti = perm[i];
2980  perm[i] = i;
2981  i = nexti;
2982  }
2983  while( perm[i] != v );
2984  consdata->vars[i] = varv;
2985  consdata->vals[i] = valv;
2986  if( consdata->eventdata != NULL )
2987  {
2988  consdata->eventdata[i] = eventdatav;
2989  consdata->eventdata[i]->varpos = i;
2990  }
2991  perm[i] = i;
2992  }
2993  }
2994 #ifdef SCIP_DEBUG
2995  /* check sorting */
2996  for( v = 0; v < nvars; ++v )
2997  {
2998  assert(perm[v] == v);
2999  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3000  }
3001 #endif
3002 }
3003 
3004 /** sorts linear constraint's variables depending on the stage of the solving process:
3005  * - during PRESOLVING
3006  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3007  * and the variables of the same type by non-decreasing variable index
3008  *
3009  * - during SOLVING
3010  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3011  * This fastens the propagation time of the constraint handler.
3012  */
3013 static
3015  SCIP* scip, /**< SCIP data structure */
3016  SCIP_CONSDATA* consdata /**< linear constraint data */
3017  )
3018 {
3019  assert(scip != NULL);
3020  assert(consdata != NULL);
3021 
3022  /* check if there are variables for sorting */
3023  if( consdata->nvars <= 1 )
3024  {
3025  consdata->sorted = TRUE;
3026  consdata->binvarssorted = TRUE;
3027  }
3028  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3029  {
3030  int* perm;
3031 
3032  /* get temporary memory to store the sorted permutation */
3033  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3034 
3035  /* call sorting method */
3036  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3037 
3038  permSortConsdata(consdata, perm, consdata->nvars);
3039 
3040  /* free temporary memory */
3041  SCIPfreeBufferArray(scip, &perm);
3042 
3043  consdata->sorted = TRUE;
3044  consdata->binvarssorted = FALSE;
3045  }
3046  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3047  {
3048  SCIP_EVENTDATA** eventdata;
3049  SCIP_VAR** vars;
3050  SCIP_Real* vals;
3051  int nvars;
3052  int v;
3053  int lastbin;
3054 
3055  nvars = consdata->nvars;
3056  vars = consdata->vars;
3057  vals = consdata->vals;
3058  eventdata = consdata->eventdata;
3059  assert(vars != NULL || nvars == 0);
3060  assert(vals != NULL || nvars == 0);
3061 
3062  lastbin = 0;
3063  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3064  for( v = 0; v < nvars; ++v )
3065  {
3066  assert( vars != NULL); /* for flexelint */
3067  assert( vals != NULL); /* for flexelint */
3068  if( SCIPvarIsBinary(vars[v]) )
3069  {
3070  /* swap variable at the end of the binary variables, if necessary */
3071  if( lastbin < v )
3072  {
3073  SCIP_VAR* tmpvar;
3074  SCIP_Real tmpval;
3075 
3076  tmpvar = vars[lastbin];
3077  tmpval = vals[lastbin];
3078 
3079  vars[lastbin] = vars[v];
3080  vals[lastbin] = vals[v];
3081 
3082  vars[v] = tmpvar;
3083  vals[v] = tmpval;
3084 
3085  if( eventdata != NULL )
3086  {
3087  SCIP_EVENTDATA* tmpeventdata;
3088 
3089  tmpeventdata = eventdata[lastbin];
3090  eventdata[lastbin] = eventdata[v];
3091  eventdata[lastbin]->varpos = lastbin;
3092  eventdata[v] = tmpeventdata;
3093  eventdata[v]->varpos = v;
3094  }
3095  assert(SCIPvarIsBinary(vars[lastbin]));
3096  }
3097 #ifndef NDEBUG
3098  else
3099  assert(lastbin == v);
3100 #endif
3101  ++lastbin;
3102  }
3103  }
3104  consdata->nbinvars = lastbin;
3105 
3106 #ifndef NDEBUG
3107  /* check sorting */
3108  for( v = 0; v < nvars; ++v )
3109  {
3110  assert(vars != NULL); /* for flexelint */
3111  assert(eventdata == NULL || eventdata[v]->varpos == v);
3112  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3113  }
3114 #endif
3115 
3116  if( consdata->nbinvars > 1 )
3117  {
3118  SCIP_Real* absvals;
3119  int* perm;
3120 
3121  assert(lastbin == consdata->nbinvars);
3122  assert(lastbin <= nvars);
3123  assert(vals != NULL);
3124 
3125  /* initialize absolute coefficients and the target permutation for binary variables */
3126  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3127  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3128 
3129  for( v = 0; v < lastbin; ++v )
3130  {
3131  absvals[v] = ABS(vals[v]);
3132  perm[v] = v;
3133  }
3134 
3135  /* execute the sorting */
3136  SCIPsortDownRealInt(absvals, perm, lastbin);
3137 
3138  permSortConsdata(consdata, perm, lastbin);
3139 
3140  /* free temporary arrays */
3141  SCIPfreeBufferArray(scip, &perm);
3142  SCIPfreeBufferArray(scip, &absvals);
3143  }
3144  consdata->binvarssorted = TRUE;
3145 
3146  /* presolve sorting cannot be guaranteed after binary sorting */
3147  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3148  }
3149  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3150  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3151 
3152  return SCIP_OKAY;
3153 }
3154 
3155 
3156 /*
3157  * local linear constraint handler methods
3158  */
3159 
3160 /** sets left hand side of linear constraint */
3161 static
3163  SCIP* scip, /**< SCIP data structure */
3164  SCIP_CONS* cons, /**< linear constraint */
3165  SCIP_Real lhs /**< new left hand side */
3166  )
3167 {
3168  SCIP_CONSDATA* consdata;
3169 
3170  assert(scip != NULL);
3171  assert(cons != NULL);
3172  assert(!SCIPisInfinity(scip, lhs));
3173 
3174  /* adjust value to not be smaller than -inf */
3175  if ( SCIPisInfinity(scip, -lhs) )
3176  lhs = -SCIPinfinity(scip);
3177 
3178  consdata = SCIPconsGetData(cons);
3179  assert(consdata != NULL);
3180  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3181  assert(!SCIPisInfinity(scip, consdata->lhs));
3182 
3183  /* check whether the side is not changed */
3184  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3185  return SCIP_OKAY;
3186 
3187  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3188  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3189  {
3190  consdata->rhs = lhs;
3191  assert(consdata->row == NULL);
3192  }
3193 
3194  /* if necessary, update the rounding locks of variables */
3195  if( SCIPconsIsLocked(cons) )
3196  {
3197  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3198  {
3199  SCIP_VAR** vars;
3200  SCIP_Real* vals;
3201  int v;
3202 
3203  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3204  vars = consdata->vars;
3205  vals = consdata->vals;
3206 
3207  for( v = 0; v < consdata->nvars; ++v )
3208  {
3209  assert(vars[v] != NULL);
3210  assert(!SCIPisZero(scip, vals[v]));
3211 
3212  if( SCIPisPositive(scip, vals[v]) )
3213  {
3214  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3215  }
3216  else
3217  {
3218  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3219  }
3220  }
3221  }
3222  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3223  {
3224  SCIP_VAR** vars;
3225  SCIP_Real* vals;
3226  int v;
3227 
3228  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3229  vars = consdata->vars;
3230  vals = consdata->vals;
3231 
3232  for( v = 0; v < consdata->nvars; ++v )
3233  {
3234  assert(vars[v] != NULL);
3235  assert(!SCIPisZero(scip, vals[v]));
3236 
3237  if( SCIPisPositive(scip, vals[v]) )
3238  {
3239  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3240  }
3241  else
3242  {
3243  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3244  }
3245  }
3246  }
3247  }
3248 
3249  /* 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 */
3250  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3251  {
3252  consdata->propagated = FALSE;
3253  consdata->boundstightened = FALSE;
3254  consdata->presolved = FALSE;
3255  consdata->cliquesadded = FALSE;
3256  consdata->implsadded = FALSE;
3257  }
3258 
3259  /* set new left hand side and update constraint data */
3260  consdata->lhs = lhs;
3261  consdata->changed = TRUE;
3262  consdata->normalized = FALSE;
3263  consdata->upgradetried = FALSE;
3264 
3265  /* update the lhs of the LP row */
3266  if( consdata->row != NULL )
3267  {
3268  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3269  }
3270 
3271  return SCIP_OKAY;
3272 }
3273 
3274 /** sets right hand side of linear constraint */
3275 static
3277  SCIP* scip, /**< SCIP data structure */
3278  SCIP_CONS* cons, /**< linear constraint */
3279  SCIP_Real rhs /**< new right hand side */
3280  )
3281 {
3282  SCIP_CONSDATA* consdata;
3283 
3284  assert(scip != NULL);
3285  assert(cons != NULL);
3286  assert(!SCIPisInfinity(scip, -rhs));
3287 
3288  /* adjust value to not be larger than inf */
3289  if ( SCIPisInfinity(scip, rhs) )
3290  rhs = SCIPinfinity(scip);
3291 
3292  consdata = SCIPconsGetData(cons);
3293  assert(consdata != NULL);
3294  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3295  assert(!SCIPisInfinity(scip, -consdata->rhs));
3296 
3297  /* check whether the side is not changed */
3298  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3299  return SCIP_OKAY;
3300 
3301  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3302  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3303  {
3304  consdata->lhs = rhs;
3305  assert(consdata->row == NULL);
3306  }
3307 
3308  /* if necessary, update the rounding locks of variables */
3309  if( SCIPconsIsLocked(cons) )
3310  {
3311  assert(SCIPconsIsTransformed(cons));
3312 
3313  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3314  {
3315  SCIP_VAR** vars;
3316  SCIP_Real* vals;
3317  int v;
3318 
3319  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3320  vars = consdata->vars;
3321  vals = consdata->vals;
3322 
3323  for( v = 0; v < consdata->nvars; ++v )
3324  {
3325  assert(vars[v] != NULL);
3326  assert(!SCIPisZero(scip, vals[v]));
3327 
3328  if( SCIPisPositive(scip, vals[v]) )
3329  {
3330  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3331  }
3332  else
3333  {
3334  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3335  }
3336  }
3337  }
3338  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3339  {
3340  SCIP_VAR** vars;
3341  SCIP_Real* vals;
3342  int v;
3343 
3344  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3345  vars = consdata->vars;
3346  vals = consdata->vals;
3347 
3348  for( v = 0; v < consdata->nvars; ++v )
3349  {
3350  assert(vars[v] != NULL);
3351  assert(!SCIPisZero(scip, vals[v]));
3352 
3353  if( SCIPisPositive(scip, vals[v]) )
3354  {
3355  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3356  }
3357  else
3358  {
3359  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3360  }
3361  }
3362  }
3363  }
3364 
3365  /* 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 */
3366  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3367  {
3368  consdata->propagated = FALSE;
3369  consdata->boundstightened = FALSE;
3370  consdata->presolved = FALSE;
3371  consdata->cliquesadded = FALSE;
3372  consdata->implsadded = FALSE;
3373  }
3374 
3375  /* set new right hand side and update constraint data */
3376  consdata->rhs = rhs;
3377  consdata->changed = TRUE;
3378  consdata->normalized = FALSE;
3379  consdata->upgradetried = FALSE;
3380 
3381  /* update the rhs of the LP row */
3382  if( consdata->row != NULL )
3383  {
3384  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3385  }
3386 
3387  return SCIP_OKAY;
3388 }
3389 
3390 /** adds coefficient in linear constraint */
3391 static
3393  SCIP* scip, /**< SCIP data structure */
3394  SCIP_CONS* cons, /**< linear constraint */
3395  SCIP_VAR* var, /**< variable of constraint entry */
3396  SCIP_Real val /**< coefficient of constraint entry */
3397  )
3398 {
3399  SCIP_CONSDATA* consdata;
3400  SCIP_Bool transformed;
3401 
3402  assert(scip != NULL);
3403  assert(cons != NULL);
3404  assert(var != NULL);
3405 
3406  /* ignore coefficient if it is nearly zero */
3407  if( SCIPisZero(scip, val) )
3408  return SCIP_OKAY;
3409 
3410  consdata = SCIPconsGetData(cons);
3411  assert(consdata != NULL);
3412 
3413  /* are we in the transformed problem? */
3414  transformed = SCIPconsIsTransformed(cons);
3415 
3416  /* always use transformed variables in transformed constraints */
3417  if( transformed )
3418  {
3419  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3420  }
3421  assert(var != NULL);
3422  assert(transformed == SCIPvarIsTransformed(var));
3423 
3424  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3425  consdata->vars[consdata->nvars] = var;
3426  consdata->vals[consdata->nvars] = val;
3427  consdata->nvars++;
3428  /* capture variable */
3429  SCIP_CALL( SCIPcaptureVar(scip, var) );
3430 
3431  /* if we are in transformed problem, the variable needs an additional event data */
3432  if( transformed )
3433  {
3434  if( consdata->eventdata != NULL )
3435  {
3436  SCIP_CONSHDLR* conshdlr;
3437  SCIP_CONSHDLRDATA* conshdlrdata;
3438 
3439  /* get event handler */
3440  conshdlr = SCIPconsGetHdlr(cons);
3441  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3442  assert(conshdlrdata != NULL);
3443  assert(conshdlrdata->eventhdlr != NULL);
3444 
3445  /* initialize eventdata array */
3446  consdata->eventdata[consdata->nvars-1] = NULL;
3447 
3448  /* catch bound change events of variable */
3449  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3450  }
3451 
3452  /* update minimum and maximum activities */
3453  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3454 
3455  /* update maximum activity delta */
3456  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3457  {
3458  SCIP_Real lb;
3459  SCIP_Real ub;
3460 
3461  lb = SCIPvarGetLbLocal(var);
3462  ub = SCIPvarGetUbLocal(var);
3463 
3464  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3465  {
3466  consdata->maxactdelta = SCIPinfinity(scip);
3467  consdata->maxactdeltavar = var;
3468  }
3469  else
3470  {
3471  SCIP_Real domain = ub - lb;
3472  SCIP_Real delta = REALABS(val) * domain;
3473 
3474  if( delta > consdata->maxactdelta )
3475  {
3476  consdata->maxactdelta = delta;
3477  consdata->maxactdeltavar = var;
3478  }
3479  }
3480  }
3481  }
3482 
3483  /* install rounding locks for new variable */
3484  SCIP_CALL( lockRounding(scip, cons, var, val) );
3485 
3486  consdata->propagated = FALSE;
3487  consdata->boundstightened = FALSE;
3488  consdata->presolved = FALSE;
3489  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3490 
3491  if( consdata->validsignature )
3492  consdataUpdateSignatures(consdata, consdata->nvars-1);
3493 
3494  consdata->changed = TRUE;
3495  consdata->normalized = FALSE;
3496  consdata->upgradetried = FALSE;
3497  consdata->cliquesadded = FALSE;
3498  consdata->implsadded = FALSE;
3499 
3500  if( consdata->nvars == 1 )
3501  {
3502  consdata->binvarssorted = TRUE;
3503  consdata->sorted = TRUE;
3504  consdata->merged = TRUE;
3505  }
3506  else
3507  {
3508  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3509  consdata->sorted = consdata->sorted
3510  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3511  consdata->merged = FALSE;
3512  }
3513 
3514  /* update hascontvar and hasnonbinvar flags */
3515  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3516  {
3517  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3518 
3519  if( vartype != SCIP_VARTYPE_BINARY )
3520  {
3521  consdata->hasnonbinvar = TRUE;
3522 
3523  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3524  consdata->hascontvar = TRUE;
3525  }
3526  }
3527 
3528  /* add the new coefficient to the LP row */
3529  if( consdata->row != NULL )
3530  {
3531  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3532  }
3533 
3534  return SCIP_OKAY;
3535 }
3536 
3537 /** deletes coefficient at given position from linear constraint data */
3538 static
3540  SCIP* scip, /**< SCIP data structure */
3541  SCIP_CONS* cons, /**< linear constraint */
3542  int pos /**< position of coefficient to delete */
3543  )
3544 {
3545  SCIP_CONSDATA* consdata;
3546  SCIP_VAR* var;
3547  SCIP_Real val;
3548 
3549  assert(scip != NULL);
3550  assert(cons != NULL);
3551 
3552  consdata = SCIPconsGetData(cons);
3553  assert(consdata != NULL);
3554  assert(0 <= pos && pos < consdata->nvars);
3555 
3556  var = consdata->vars[pos];
3557  val = consdata->vals[pos];
3558  assert(var != NULL);
3559 
3560  /* remove rounding locks for deleted variable */
3561  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3562 
3563  /* if we are in transformed problem, delete the event data of the variable */
3564  if( SCIPconsIsTransformed(cons) )
3565  {
3566  SCIP_CONSHDLR* conshdlr;
3567  SCIP_CONSHDLRDATA* conshdlrdata;
3568 
3569  /* get event handler */
3570  conshdlr = SCIPconsGetHdlr(cons);
3571  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3572  assert(conshdlrdata != NULL);
3573  assert(conshdlrdata->eventhdlr != NULL);
3574 
3575  /* drop bound change events of variable */
3576  if( consdata->eventdata != NULL )
3577  {
3578  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3579  assert(consdata->eventdata[pos] == NULL);
3580  }
3581  }
3582 
3583  /* move the last variable to the free slot */
3584  if( pos != consdata->nvars-1 )
3585  {
3586  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3587 
3588  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3589  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3590 
3591  if( consdata->eventdata != NULL )
3592  {
3593  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3594  assert(consdata->eventdata[pos] != NULL);
3595  consdata->eventdata[pos]->varpos = pos;
3596  }
3597  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3598  }
3599  consdata->nvars--;
3600 
3601  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3602  * of the remaining variable, or give exactly 0.0)
3603  */
3604  if( consdata->nvars <= 1 )
3605  consdataInvalidateActivities(consdata);
3606  else
3607  {
3608  if( SCIPconsIsTransformed(cons) )
3609  {
3610  /* if we are in transformed problem, update minimum and maximum activities */
3611  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3612 
3613  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3614  * delta needs to be recalculated on the next real propagation
3615  */
3616  if( consdata->maxactdeltavar == var )
3617  {
3618  consdata->maxactdelta = SCIP_INVALID;
3619  consdata->maxactdeltavar = NULL;
3620  }
3621  }
3622  }
3623 
3624  consdata->propagated = FALSE;
3625  consdata->boundstightened = FALSE;
3626  consdata->presolved = FALSE;
3627  consdata->validsignature = FALSE;
3628  consdata->changed = TRUE;
3629  consdata->normalized = FALSE;
3630  consdata->upgradetried = FALSE;
3631  consdata->cliquesadded = FALSE;
3632  consdata->implsadded = FALSE;
3633 
3634  /* check if hasnonbinvar flag might be incorrect now */
3635  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3636  {
3637  consdata->hasnonbinvalid = FALSE;
3638  }
3639 
3640  /* delete coefficient from the LP row */
3641  if( consdata->row != NULL )
3642  {
3643  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3644  }
3645 
3646  /* release variable */
3647  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3648 
3649  return SCIP_OKAY;
3650 }
3651 
3652 /** changes coefficient value at given position of linear constraint data */
3653 static
3655  SCIP* scip, /**< SCIP data structure */
3656  SCIP_CONS* cons, /**< linear constraint */
3657  int pos, /**< position of coefficient to delete */
3658  SCIP_Real newval /**< new value of coefficient */
3659  )
3660 {
3661  SCIP_CONSDATA* consdata;
3662  SCIP_VAR* var;
3663  SCIP_Real val;
3664 
3665  assert(scip != NULL);
3666  assert(cons != NULL);
3667  assert(!SCIPisZero(scip, newval));
3669  consdata = SCIPconsGetData(cons);
3670  assert(consdata != NULL);
3671  assert(0 <= pos && pos < consdata->nvars);
3672  assert(!SCIPisZero(scip, newval));
3673 
3674  var = consdata->vars[pos];
3675  val = consdata->vals[pos];
3676  assert(var != NULL);
3677  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3678 
3679  /* if necessary, update the rounding locks of the variable */
3680  if( SCIPconsIsLocked(cons) && newval * val < 0.0 )
3681  {
3682  assert(SCIPconsIsTransformed(cons));
3683 
3684  /* remove rounding locks for variable with old coefficient */
3685  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3686 
3687  /* install rounding locks for variable with new coefficient */
3688  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3689  }
3690 
3691  /* change the value */
3692  consdata->vals[pos] = newval;
3693 
3694  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3695 
3696  /* update minimum and maximum activities */
3697  if( SCIPconsIsTransformed(cons) )
3698  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3699 
3700  consdata->propagated = FALSE;
3701  consdata->boundstightened = FALSE;
3702  consdata->presolved = FALSE;
3703  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3704  consdata->changed = TRUE;
3705  consdata->normalized = FALSE;
3706  consdata->upgradetried = FALSE;
3707  consdata->cliquesadded = FALSE;
3708  consdata->implsadded = FALSE;
3709 
3710  return SCIP_OKAY;
3711 }
3712 
3713 /** scales a linear constraint with a constant scalar */
3714 static
3716  SCIP* scip, /**< SCIP data structure */
3717  SCIP_CONS* cons, /**< linear constraint to scale */
3718  SCIP_Real scalar /**< value to scale constraint with */
3719  )
3720 {
3721  SCIP_CONSDATA* consdata;
3722  SCIP_Real newval;
3723  SCIP_Real absscalar;
3724  int i;
3725 
3726  assert(scip != NULL);
3727  assert(cons != NULL);
3728 
3729  consdata = SCIPconsGetData(cons);
3730  assert(consdata != NULL);
3731  assert(consdata->row == NULL);
3732  assert(!SCIPisEQ(scip, scalar, 1.0));
3733 
3734  /* scale the coefficients */
3735  for( i = consdata->nvars - 1; i >= 0; --i )
3736  {
3737  newval = scalar * consdata->vals[i];
3738 
3739  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3740  * flooring down our new value
3741  */
3742  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
3743  newval = SCIPfeasFloor(scip, newval + 0.5);
3744 
3745  if( SCIPisZero(scip, newval) )
3746  {
3747  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
3748  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
3749  SCIP_CALL( delCoefPos(scip, cons, i) );
3750  }
3751  else
3752  consdata->vals[i] = newval;
3753  }
3754 
3755  /* scale the sides */
3756  if( scalar < 0.0 )
3757  {
3758  SCIP_Real lhs;
3759 
3760  lhs = consdata->lhs;
3761  consdata->lhs = -consdata->rhs;
3762  consdata->rhs = -lhs;
3763  }
3764  absscalar = REALABS(scalar);
3765  if( !SCIPisInfinity(scip, -consdata->lhs) )
3766  {
3767  newval = absscalar * consdata->lhs;
3768 
3769  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3770  * flooring down our new value
3771  */
3772  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
3773  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
3774  else
3775  consdata->lhs = newval;
3776  }
3777  if( !SCIPisInfinity(scip, consdata->rhs) )
3778  {
3779  newval = absscalar * consdata->rhs;
3780 
3781  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
3782  * our new value
3783  */
3784  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
3785  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
3786  else
3787  consdata->rhs = newval;
3788  }
3789 
3790  consdataInvalidateActivities(consdata);
3791  consdata->cliquesadded = FALSE;
3792  consdata->implsadded = FALSE;
3793 
3794  return SCIP_OKAY;
3795 }
3796 
3797 /* perform deletion of variables in all constraints of the constraint handler */
3798 static
3800  SCIP* scip, /**< SCIP data structure */
3801  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3802  SCIP_CONS** conss, /**< array of constraints */
3803  int nconss /**< number of constraints */
3804  )
3805 {
3806  SCIP_CONSDATA* consdata;
3807  int i;
3808  int v;
3809 
3810  assert(scip != NULL);
3811  assert(conshdlr != NULL);
3812  assert(conss != NULL);
3813  assert(nconss >= 0);
3814  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3815 
3816  /* iterate over all constraints */
3817  for( i = 0; i < nconss; i++ )
3818  {
3819  consdata = SCIPconsGetData(conss[i]);
3820 
3821  /* constraint is marked, that some of its variables were deleted */
3822  if( consdata->varsdeleted )
3823  {
3824  /* iterate over all variables of the constraint and delete them from the constraint */
3825  for( v = consdata->nvars - 1; v >= 0; --v )
3826  {
3827  if( SCIPvarIsDeleted(consdata->vars[v]) )
3828  {
3829  SCIP_CALL( delCoefPos(scip, conss[i], v) );
3830  }
3831  }
3832  consdata->varsdeleted = FALSE;
3833  }
3834  }
3835 
3836  return SCIP_OKAY;
3837 }
3838 
3839 
3840 /** normalizes a linear constraint with the following rules:
3841  * - if all coefficients have them same absolute value, change them to (-)1.0
3842  * - multiplication with +1 or -1:
3843  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
3844  * if the current rule doesn't determine the sign):
3845  * 1. the right hand side must not be negative
3846  * 2. the right hand side must not be infinite
3847  * 3. the absolute value of the right hand side must be greater than that of the left hand side
3848  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
3849  * 5. multiply with +1
3850  * - rationals to integrals
3851  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
3852  * by the smallest common multiple of all denominators to get integral coefficients.
3853  * Forbid large denominators due to numerical stability.
3854  * - division by greatest common divisor
3855  * If all coefficients are integral, divide them by the greatest common divisor.
3856  */
3857 static
3859  SCIP* scip, /**< SCIP data structure */
3860  SCIP_CONS* cons /**< linear constraint to normalize */
3861  )
3862 {
3863  SCIP_CONSDATA* consdata;
3864  SCIP_VAR** vars;
3865  SCIP_Real* vals;
3866  SCIP_Longint scm;
3867  SCIP_Longint nominator;
3868  SCIP_Longint denominator;
3869  SCIP_Longint gcd;
3870  SCIP_Longint maxmult;
3871  SCIP_Real epsilon;
3872  SCIP_Real feastol;
3873  SCIP_Real maxabsval;
3874  SCIP_Bool success;
3875  SCIP_Bool onlyintegral;
3876  int nvars;
3877  int mult;
3878  int nposcoeffs;
3879  int nnegcoeffs;
3880  int i;
3881  int v;
3882 
3883  assert(scip != NULL);
3884  assert(cons != NULL);
3885 
3886  /* we must not change a modifiable constraint in any way */
3887  if( SCIPconsIsModifiable(cons) )
3888  return SCIP_OKAY;
3889 
3890  /* get constraint data */
3891  consdata = SCIPconsGetData(cons);
3892  assert(consdata != NULL);
3893 
3894  /* check, if the constraint is already normalized */
3895  if( consdata->normalized )
3896  return SCIP_OKAY;
3897 
3898  /* get coefficient arrays */
3899  vals = consdata->vals;
3900  nvars = consdata->nvars;
3901  vars = consdata->vars;
3902  assert(nvars == 0 || vars != NULL);
3903  assert(nvars == 0 || vals != NULL);
3904 
3905  if( nvars == 0 )
3906  {
3907  consdata->normalized = TRUE;
3908  return SCIP_OKAY;
3909  }
3910 
3911  assert(vars != NULL);
3912  assert(vals != NULL);
3913 
3914  /* get maximal absolute coefficient */
3915  maxabsval = consdataGetMaxAbsval(consdata);
3916 
3917  /* check if all coefficients are in absolute value equal, and not 1.0 */
3918  if( !SCIPisEQ(scip, maxabsval, 1.0) )
3919  {
3920  SCIP_Bool abscoefsequ;
3921 
3922  abscoefsequ = TRUE;
3923 
3924  for( v = nvars - 1; v >= 0; --v )
3925  {
3926  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
3927  {
3928  abscoefsequ = FALSE;
3929  break;
3930  }
3931  }
3932 
3933  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
3934  if( abscoefsequ )
3935  {
3936  SCIPdebugMessage("divide linear constraint with %g, because all coefficents are in absolute value the same\n", maxabsval);
3937  SCIPdebugPrintCons(scip, cons, NULL);
3938  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
3939 
3940  if( consdata->validmaxabsval )
3941  {
3942  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
3943  consdata->maxabsval = 1.0;
3944 
3945  maxabsval = 1.0;
3946  }
3947  else
3948  {
3949  /* get maximal absolute coefficient */
3950  maxabsval = consdataGetMaxAbsval(consdata);
3951  }
3952 
3953  /* get new consdata information, because scalecons() might have deleted variables */
3954  vals = consdata->vals;
3955  nvars = consdata->nvars;
3956  vars = consdata->vars;
3957 
3958  assert(nvars == 0 || vars != NULL);
3959  assert(nvars == 0 || vals != NULL);
3960  }
3961  }
3962 
3963  /* nvars might have changed */
3964  if( nvars == 0 )
3965  {
3966  consdata->normalized = TRUE;
3967  return SCIP_OKAY;
3968  }
3969 
3970  assert(vars != NULL);
3971  assert(vals != NULL);
3972 
3973  /* calculate the maximal multiplier for common divisor calculation:
3974  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
3975  * which means, a value of feastol/epsilon should be used as maximal multiplier;
3976  * additionally, we don't want to scale the constraint if this would lead to too
3977  * large coefficients
3978  */
3979  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
3980  feastol = SCIPfeastol(scip);
3981  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
3982  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
3983 
3984  if( !consdata->hasnonbinvalid )
3985  consdataCheckNonbinvar(consdata);
3986 
3987  /* if all variables are of integral type we will allow a greater multiplier */
3988  if( !consdata->hascontvar )
3989  {
3990  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
3991  {
3992  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
3993  }
3994  }
3995  else
3996  {
3997  SCIP_Bool foundcont;
3998 
3999  foundcont = FALSE;
4000 
4001  for( v = nvars - 1; v >= 0; --v )
4002  {
4003  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4004  {
4005  foundcont = TRUE;
4006  break;
4007  }
4008  }
4009 
4010  if( !foundcont )
4011  {
4012  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4013  }
4014  }
4015 
4016  /*
4017  * multiplication with +1 or -1
4018  */
4019  mult = 0;
4020 
4021  /* 1. the right hand side must not be negative */
4022  if( SCIPisPositive(scip, consdata->lhs) )
4023  mult = +1;
4024  else if( SCIPisNegative(scip, consdata->rhs) )
4025  mult = -1;
4026 
4027  if( mult == 0 )
4028  {
4029  /* 2. the right hand side must not be infinite */
4030  if( SCIPisInfinity(scip, -consdata->lhs) )
4031  mult = +1;
4032  else if( SCIPisInfinity(scip, consdata->rhs) )
4033  mult = -1;
4034  }
4035 
4036  if( mult == 0 )
4037  {
4038  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4039  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4040  mult = +1;
4041  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4042  mult = -1;
4043  }
4044 
4045  if( mult == 0 )
4046  {
4047  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4048  nposcoeffs = 0;
4049  nnegcoeffs = 0;
4050  for( i = 0; i < nvars; ++i )
4051  {
4052  if( vals[i] > 0.0 )
4053  nposcoeffs++;
4054  else
4055  nnegcoeffs++;
4056  }
4057  if( nposcoeffs > nnegcoeffs )
4058  mult = +1;
4059  else if( nposcoeffs < nnegcoeffs )
4060  mult = -1;
4061  }
4062 
4063  if( mult == 0 )
4064  {
4065  /* 5. multiply with +1 */
4066  mult = +1;
4067  }
4068 
4069  assert(mult == +1 || mult == -1);
4070  if( mult == -1 )
4071  {
4072  /* scale the constraint with -1 */
4073  SCIPdebugMessage("multiply linear constraint with -1.0\n");
4074  SCIPdebugPrintCons(scip, cons, NULL);
4075  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4076 
4077  /* scalecons() can delete variables, but scaling with -1 should not do that */
4078  assert(nvars == consdata->nvars);
4079  }
4080 
4081  /*
4082  * rationals to integrals
4083  *
4084  * @todo try scaling only on behalf of non-continuous variables
4085  */
4086  success = TRUE;
4087  scm = 1;
4088  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4089  {
4090  if( !SCIPisIntegral(scip, vals[i]) )
4091  {
4092  /* epsilon has been slightly decreased above - to be on the safe side */
4093  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4094  if( success )
4095  scm = SCIPcalcSmaComMul(scm, denominator);
4096  }
4097  }
4098  assert(scm >= 1);
4099 
4100  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4101  * their greatest common divisor
4102  */
4103  onlyintegral = TRUE;
4104  if( scm == 1 )
4105  {
4106  for( i = nvars - 1; i >= 0; --i )
4107  {
4108  if( !SCIPisIntegral(scip, vals[i]) )
4109  {
4110  onlyintegral = FALSE;
4111  break;
4112  }
4113  }
4114  }
4115 
4116  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4117  if( success && scm != 1 )
4118  {
4119  /* scale the constraint with the smallest common multiple of all denominators */
4120  SCIPdebugMessage("scale linear constraint with %"SCIP_LONGINT_FORMAT" to make coefficients integral\n", scm);
4121  SCIPdebugPrintCons(scip, cons, NULL);
4122  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4123 
4124  if( consdata->validmaxabsval )
4125  {
4126  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4127  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4128  {
4129  consdata->validmaxabsval = FALSE;
4130  consdata->maxabsval = SCIP_INVALID;
4131  consdataCalcMaxAbsval(consdata);
4132  }
4133  }
4134 
4135  /* get new consdata information, because scalecons() might have deleted variables */
4136  vals = consdata->vals;
4137  nvars = consdata->nvars;
4138  assert(nvars == 0 || vals != NULL);
4139  }
4140 
4141  /*
4142  * division by greatest common divisor
4143  */
4144  if( success && nvars >= 1 )
4145  {
4146  /* all coefficients are integral: divide them by their greatest common divisor */
4147  assert(SCIPisIntegral(scip, vals[0]));
4148 
4149  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4150  for( i = 1; i < nvars && gcd > 1; ++i )
4151  {
4152  assert(SCIPisIntegral(scip, vals[i]));
4153  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4154  }
4155 
4156  if( gcd > 1 )
4157  {
4158  /* divide the constraint by the greatest common divisor of the coefficients */
4159  SCIPdebugMessage("divide linear constraint by greatest common divisor %"SCIP_LONGINT_FORMAT"\n", gcd);
4160  SCIPdebugPrintCons(scip, cons, NULL);
4161  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4162 
4163  if( consdata->validmaxabsval )
4164  {
4165  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4166  }
4167  }
4168  }
4169 
4170  /* mark constraint to be normalized */
4171  consdata->normalized = TRUE;
4172 
4173  SCIPdebugMessage("normalized constraint:\n");
4174  SCIPdebugPrintCons(scip, cons, NULL);
4175 
4176  return SCIP_OKAY;
4177 }
4178 
4179 /** replaces multiple occurrences of a variable by a single coefficient */
4180 static
4182  SCIP* scip, /**< SCIP data structure */
4183  SCIP_CONS* cons /**< linear constraint */
4184  )
4185 {
4186  SCIP_CONSDATA* consdata;
4187  SCIP_VAR* var;
4188  SCIP_Real valsum;
4189  int v;
4190 
4191  assert(scip != NULL);
4192  assert(cons != NULL);
4193 
4194  consdata = SCIPconsGetData(cons);
4195  assert(consdata != NULL);
4196 
4197  if( consdata->merged )
4198  return SCIP_OKAY;
4199 
4200  /* sort the constraint */
4201  SCIP_CALL( consdataSort(scip, consdata) );
4202 
4203  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4204  * backward direction is necessary, since delCoefPos() modifies the given position and
4205  * the subsequent ones
4206  */
4207  v = consdata->nvars-1;
4208  while( v >= 1 )
4209  {
4210  var = consdata->vars[v];
4211  if( consdata->vars[v-1] == var )
4212  {
4213  valsum = consdata->vals[v];
4214  do
4215  {
4216  SCIP_CALL( delCoefPos(scip, cons, v) );
4217  --v;
4218  valsum += consdata->vals[v];
4219  }
4220  while( v >= 1 && consdata->vars[v-1] == var );
4221 
4222  /* modify the last existing occurrence of the variable */
4223  assert(consdata->vars[v] == var);
4224  if( SCIPisZero(scip, valsum) )
4225  {
4226  SCIP_CALL( delCoefPos(scip, cons, v) );
4227 
4228  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4229  * delta needs to be recalculated on the next real propagation
4230  */
4231  if( consdata->maxactdeltavar == var )
4232  {
4233  consdata->maxactdelta = SCIP_INVALID;
4234  consdata->maxactdeltavar = NULL;
4235  }
4236  }
4237  else
4238  {
4239  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4240  }
4241  }
4242  --v;
4243  }
4244 
4245  consdata->merged = TRUE;
4246 
4247  return SCIP_OKAY;
4248 }
4249 
4250 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4251 static
4253  SCIP* scip, /**< SCIP data structure */
4254  SCIP_CONS* cons, /**< linear constraint */
4255  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4256  * information is not needed; in this case, we apply all fixings
4257  * instead of stopping after the first infeasible one */
4258  )
4259 {
4260  SCIP_CONSDATA* consdata;
4261  SCIP_VAR* var;
4262  SCIP_VAR** aggrvars;
4263  SCIP_Real val;
4264  SCIP_Real* aggrscalars;
4265  SCIP_Real fixedval;
4266  SCIP_Real aggrconst;
4267  int v;
4268  int naggrvars;
4269  int i;
4270 
4271  assert(scip != NULL);
4272  assert(cons != NULL);
4273 
4274  if( infeasible != NULL )
4275  *infeasible = FALSE;
4276 
4277  consdata = SCIPconsGetData(cons);
4278  assert(consdata != NULL);
4279 
4280  if( !consdata->removedfixings )
4281  {
4282  SCIP_Real lhssubtrahend;
4283  SCIP_Real rhssubtrahend;
4284 
4285  lhssubtrahend = 0.0;
4286  rhssubtrahend = 0.0;
4287 
4288  SCIPdebugMessage("applying fixings:\n");
4289  SCIPdebugPrintCons(scip, cons, NULL);
4290 
4291  v = 0;
4292  while( v < consdata->nvars )
4293  {
4294  var = consdata->vars[v];
4295  val = consdata->vals[v];
4296  assert(SCIPvarIsTransformed(var));
4297 
4298  switch( SCIPvarGetStatus(var) )
4299  {
4301  SCIPerrorMessage("original variable in transformed linear constraint\n");
4302  return SCIP_INVALIDDATA;
4303 
4304  case SCIP_VARSTATUS_LOOSE:
4305  case SCIP_VARSTATUS_COLUMN:
4306  ++v;
4307  break;
4308 
4309  case SCIP_VARSTATUS_FIXED:
4310  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4311  fixedval = SCIPvarGetLbGlobal(var);
4312  if( !SCIPisInfinity(scip, -consdata->lhs) )
4313  {
4314  if( SCIPisInfinity(scip, ABS(fixedval)) )
4315  {
4316  if( val * fixedval > 0.0 )
4317  {
4318  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4319  }
4320  else
4321  {
4322  if( infeasible != NULL )
4323  {
4324  /* if lhs gets infinity it means that the problem is infeasible */
4325  *infeasible = TRUE;
4326  return SCIP_OKAY;
4327  }
4328  else
4329  {
4330  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4331  }
4332  }
4333  }
4334  else
4335  lhssubtrahend += val * fixedval;
4336  }
4337  if( !SCIPisInfinity(scip, consdata->rhs) )
4338  {
4339  if( SCIPisInfinity(scip, ABS(fixedval)) )
4340  {
4341  if( val * fixedval > 0.0 )
4342  {
4343  if( infeasible != NULL )
4344  {
4345  /* if rhs gets -infinity it means that the problem is infeasible */
4346  *infeasible = TRUE;
4347  return SCIP_OKAY;
4348  }
4349  else
4350  {
4351  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4352  }
4353  }
4354  else
4355  {
4356  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4357  }
4358  }
4359  else
4360  rhssubtrahend += val * fixedval;
4361  }
4362  SCIP_CALL( delCoefPos(scip, cons, v) );
4363  break;
4364 
4366  {
4367  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4368  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4369  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4370 
4371  assert(activevar != NULL);
4372  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4373  assert(activevar != NULL);
4374 
4375  if( !SCIPisZero(scip, activescalar) )
4376  {
4377  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4378  }
4379 
4380  if( !SCIPisZero(scip, activeconstant) )
4381  {
4382  if( !SCIPisInfinity(scip, -consdata->lhs) )
4383  lhssubtrahend += activeconstant;
4384  if( !SCIPisInfinity(scip, consdata->rhs) )
4385  rhssubtrahend += activeconstant;
4386  }
4387 
4388  SCIP_CALL( delCoefPos(scip, cons, v) );
4389  break;
4390  }
4393  naggrvars = SCIPvarGetMultaggrNVars(var);
4394  aggrvars = SCIPvarGetMultaggrVars(var);
4395  aggrscalars = SCIPvarGetMultaggrScalars(var);
4396  for( i = 0; i < naggrvars; ++i )
4397  {
4398  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4399  }
4400  aggrconst = SCIPvarGetMultaggrConstant(var);
4401 
4402  if( !SCIPisInfinity(scip, -consdata->lhs) )
4403  lhssubtrahend += val * aggrconst;
4404  if( !SCIPisInfinity(scip, consdata->rhs) )
4405  rhssubtrahend += val * aggrconst;
4406 
4407  SCIP_CALL( delCoefPos(scip, cons, v) );
4408  break;
4409 
4411  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4412  aggrconst = SCIPvarGetNegationConstant(var);
4413 
4414  if( !SCIPisInfinity(scip, -consdata->lhs) )
4415  lhssubtrahend += val * aggrconst;
4416  if( !SCIPisInfinity(scip, consdata->rhs) )
4417  rhssubtrahend += val * aggrconst;
4418 
4419  SCIP_CALL( delCoefPos(scip, cons, v) );
4420  break;
4421 
4422  default:
4423  SCIPerrorMessage("unknown variable status\n");
4424  SCIPABORT();
4425  return SCIP_INVALIDDATA; /*lint !e527*/
4426  }
4427  }
4428 
4429  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4430  {
4431  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4432  * causing wrong fixings of other variables --> better use a real zero here;
4433  * for small numbers, polishing the difference might lead to wrong results -->
4434  * better use the exact difference in this case
4435  */
4436  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4437  {
4438  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4439  }
4440  else
4441  {
4442  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4443  }
4444  }
4445  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4446  {
4447 
4448  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4449  * causing wrong fixings of other variables --> better use a real zero here;
4450  * for small numbers, polishing the difference might lead to wrong results -->
4451  * better use the exact difference in this case
4452  */
4453  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4454  {
4455  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4456  }
4457  else
4458  {
4459  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4460  }
4461  }
4462 
4463  consdata->removedfixings = TRUE;
4464 
4465  SCIPdebugMessage("after fixings:\n");
4466  SCIPdebugPrintCons(scip, cons, NULL);
4467 
4468  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4469  * to clean up the constraint
4470  */
4471  SCIP_CALL( mergeMultiples(scip, cons) );
4472 
4473  SCIPdebugMessage("after merging:\n");
4474  SCIPdebugPrintCons(scip, cons, NULL);
4475  }
4476  assert(consdata->removedfixings);
4477 
4478 #ifndef NDEBUG
4479  /* check, if all fixings are applied */
4480  for( v = 0; v < consdata->nvars; ++v )
4481  assert(SCIPvarIsActive(consdata->vars[v]));
4482 #endif
4483 
4484  return SCIP_OKAY;
4485 }
4486 
4487 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4488  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4489  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4490  * conflict detecting constraint by using NULL as inferred variable
4491  */
4492 static
4494  SCIP* scip, /**< SCIP data structure */
4495  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4496  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4497  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4498  int inferpos, /**< position of the inferred variable in the vars array */
4499  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4500  )
4501 {
4502  SCIP_CONSDATA* consdata;
4503  SCIP_VAR** vars;
4504  SCIP_Real* vals;
4505  int nvars;
4506  int i;
4508  assert(scip != NULL);
4509  assert(cons != NULL);
4510 
4511  consdata = SCIPconsGetData(cons);
4512  assert(consdata != NULL);
4513  vars = consdata->vars;
4514  vals = consdata->vals;
4515  nvars = consdata->nvars;
4516  assert(vars != NULL || nvars == 0);
4517  assert(vals != NULL || nvars == 0);
4518  assert(-1 <= inferpos && inferpos < nvars);
4519  assert((infervar == NULL) == (inferpos == -1));
4520  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4521 
4522  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4523  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4524  * - if the right hand side is the reason, the minimal residual activity is responsible
4525  * - if the left hand side is the reason, the maximal residual activity is responsible
4526  */
4527 
4528  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4529  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4530  {
4531  SCIP_Real minresactivity;
4532  SCIP_Real maxresactivity;
4533  SCIP_Bool minisrelax;
4534  SCIP_Bool maxisrelax;
4535  SCIP_Bool isminsettoinfinity;
4536  SCIP_Bool ismaxsettoinfinity;
4537 
4538  minresactivity = -SCIPinfinity(scip);
4539  maxresactivity = SCIPinfinity(scip);
4540 
4541  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4542  if( infervar != NULL )
4543  {
4544  assert(vals != NULL); /* for flexelint */
4545  if( reasonisrhs )
4546  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4547  &minisrelax, NULL, &isminsettoinfinity, NULL);
4548  else
4549  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4550  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4551  }
4552  else
4553  {
4554  if( reasonisrhs )
4555  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4556  &minisrelax, NULL, &isminsettoinfinity, NULL);
4557  else
4558  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4559  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4560  }
4561 
4562  /* we can only do something clever, if the residual activity is finite and not relaxed */
4563  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4564  {
4565  SCIP_Real rescap;
4566  SCIP_Bool resactisinf;
4567 
4568  resactisinf = FALSE;
4569 
4570  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4571  * than its inferred bound
4572  */
4573  if( infervar != NULL )
4574  {
4575  assert(vals != NULL); /* for flexelint */
4576 
4577  if( reasonisrhs )
4578  {
4579  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4580  {
4581  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4582  if( SCIPisInfinity(scip, -minresactivity) )
4583  resactisinf = TRUE;
4584  }
4585  rescap = consdata->rhs - minresactivity;
4586  }
4587  else
4588  {
4589  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4590  {
4591  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4592  if( SCIPisInfinity(scip, maxresactivity) )
4593  resactisinf = TRUE;
4594  }
4595  rescap = consdata->lhs - maxresactivity;
4596  }
4597 
4598  if( reasonisrhs == (vals[inferpos] > 0.0) )
4599  rescap -= vals[inferpos] * (SCIPvarGetUbAtIndex(infervar, bdchgidx, TRUE) + 1.0);
4600  else
4601  rescap -= vals[inferpos] * (SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE) - 1.0);
4602  }
4603  else
4604  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4605 
4606  if( !resactisinf )
4607  {
4608  /* now add bounds as reasons until the residual capacity is exceeded */
4609  for( i = 0; i < nvars; ++i )
4610  {
4611  assert(vars != NULL); /* for flexelint */
4612  assert(vals != NULL); /* for flexelint */
4613 
4614  /* zero coefficients and the infered variable can be ignored */
4615  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4616  continue;
4617 
4618  /* check if the residual capacity is exceeded */
4619  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4620  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4621  break;
4622 
4623  /* update the residual capacity due to the local bound of this variable */
4624  if( reasonisrhs == (vals[i] > 0.0) )
4625  {
4626  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4627  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4628  rescap -= vals[i] * (SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4629  }
4630  else
4631  {
4632  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4633  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4634  rescap -= vals[i] * (SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4635  }
4636  }
4637  return SCIP_OKAY;
4638  }
4639  }
4640  }
4641 
4642  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4643  for( i = 0; i < nvars; ++i )
4644  {
4645  assert(vars != NULL); /* for flexelint */
4646  assert(vals != NULL); /* for flexelint */
4647 
4648  /* zero coefficients and the infered variable can be ignored */
4649  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4650  continue;
4651 
4652  if( reasonisrhs == (vals[i] > 0.0) )
4653  {
4654  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4655  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4656  }
4657  else
4658  {
4659  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4660  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4661  }
4662  }
4663 
4664  return SCIP_OKAY;
4665 }
4666 
4667 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
4668  * propagation rule (see propagateCons()):
4669  * (1) activity residuals of all other variables tighten bounds of single variable
4670  */
4671 static
4673  SCIP* scip, /**< SCIP data structure */
4674  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4675  SCIP_VAR* infervar, /**< variable that was deduced */
4676  INFERINFO inferinfo, /**< inference information */
4677  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
4678  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4679  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
4680  )
4681 {
4682  SCIP_CONSDATA* consdata;
4683  SCIP_VAR** vars;
4684 #ifndef NDEBUG
4685  SCIP_Real* vals;
4686 #endif
4687  int nvars;
4688  int inferpos;
4689 
4690  assert(scip != NULL);
4691  assert(cons != NULL);
4692  assert(result != NULL);
4693 
4694  consdata = SCIPconsGetData(cons);
4695  assert(consdata != NULL);
4696  vars = consdata->vars;
4697  nvars = consdata->nvars;
4698 #ifndef NDEBUG
4699  vals = consdata->vals;
4700  assert(vars != NULL);
4701  assert(vals != NULL);
4702 #endif
4703 
4704  /* get the position of the inferred variable in the vars array */
4705  inferpos = inferInfoGetPos(inferinfo);
4706  if( inferpos >= nvars || vars[inferpos] != infervar )
4707  {
4708  /* find inference variable in constraint */
4709  /**@todo use a binary search here; the variables can be sorted by variable index */
4710  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
4711  {}
4712  }
4713  assert(inferpos < nvars);
4714  assert(vars[inferpos] == infervar);
4715  assert(!SCIPisZero(scip, vals[inferpos]));
4716 
4717  switch( inferInfoGetProprule(inferinfo) )
4718  {
4719  case PROPRULE_1_RHS:
4720  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
4721  * constraint (only taking the other variables into account) didn't leave enough space for a larger
4722  * domain in order to not exceed the right hand side of the inequality
4723  */
4724  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
4725  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
4726  *result = SCIP_SUCCESS;
4727  break;
4728 
4729  case PROPRULE_1_LHS:
4730  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
4731  * constraint (only taking the other variables into account) didn't leave enough space for a larger
4732  * domain in order to not fall below the left hand side of the inequality
4733  */
4734  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
4735  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
4736  *result = SCIP_SUCCESS;
4737  break;
4738 
4739  case PROPRULE_INVALID:
4740  default:
4741  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
4742  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
4743  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
4744  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
4745  SCIPinfoMessage(scip, NULL, ";\n");
4746  return SCIP_INVALIDDATA;
4747  }
4748 
4749  return SCIP_OKAY;
4750 }
4751 
4752 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
4753 static
4755  SCIP* scip, /**< SCIP data structure */
4756  SCIP_CONS* cons, /**< conflict detecting constraint */
4757  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
4758  )
4759 {
4760  /* conflict analysis can only be applied in solving stage and if it is turned on */
4762  return SCIP_OKAY;
4763 
4764  /* initialize conflict analysis */
4766 
4767  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
4768  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
4769 
4770  /* analyze the conflict */
4771  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
4772 
4773  return SCIP_OKAY;
4774 }
4775 
4776 /** check if there is any hope of tightening some bounds */
4777 static
4779  SCIP* scip, /**< SCIP data structure */
4780  SCIP_CONS* cons /**< linear constraint */
4781  )
4782 {
4783  SCIP_CONSDATA* consdata;
4784  int infcountmin;
4785  int infcountmax;
4786 
4787  consdata = SCIPconsGetData(cons);
4788  assert(consdata != NULL);
4789 
4790  infcountmin = consdata->minactivityneginf
4791  + consdata->minactivityposinf
4792  + consdata->minactivityneghuge
4793  + consdata->minactivityposhuge;
4794  infcountmax = consdata->maxactivityneginf
4795  + consdata->maxactivityposinf
4796  + consdata->maxactivityneghuge
4797  + consdata->maxactivityposhuge;
4798 
4799  if( infcountmin > 1 && infcountmax > 1 )
4800  return FALSE;
4801 
4802  return TRUE;
4803 }
4804 
4805 /** tighten upper bound */
4806 static
4808  SCIP* scip, /**< SCIP data structure */
4809  SCIP_CONS* cons, /**< linear constraint */
4810  int pos, /**< variable position */
4811  PROPRULE proprule, /**< propagation rule that deduced the value */
4812  SCIP_Real newub, /**< new upper bound */
4813  SCIP_Real oldub, /**< old upper bound */
4814  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4815  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4816  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4817  )
4818 {
4819  SCIP_CONSDATA* consdata;
4820  SCIP_VAR* var;
4822  SCIP_Bool infeasible;
4823  SCIP_Bool tightened;
4824 
4825  assert(cons != NULL);
4826  assert(!SCIPisInfinity(scip, newub));
4827 
4828  consdata = SCIPconsGetData(cons);
4829  assert(consdata != NULL);
4830  var = consdata->vars[pos];
4831  assert(var != NULL);
4832 
4833  lb = SCIPvarGetLbLocal(var);
4834  newub = SCIPadjustedVarUb(scip, var, newub);
4835 
4836  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
4837  {
4838  SCIP_VARTYPE vartype;
4839 
4840  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
4841  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
4842 
4843  vartype = SCIPvarGetType(var);
4844 
4845  /* tighten upper bound */
4846  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
4847 
4848  if( infeasible )
4849  {
4850  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4851  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4852 
4853  /* analyze conflict */
4854  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
4855 
4856  *cutoff = TRUE;
4857  }
4858  else if( tightened )
4859  {
4860  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
4861  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4862  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
4863 
4864  (*nchgbds)++;
4865 
4866  /* if variable type was changed we might be able to upgrade the constraint */
4867  if( vartype != SCIPvarGetType(var) )
4868  consdata->upgradetried = FALSE;
4869  }
4870  }
4871  return SCIP_OKAY;
4872 }
4873 
4874 /** tighten lower bound */
4875 static
4877  SCIP* scip, /**< SCIP data structure */
4878  SCIP_CONS* cons, /**< linear constraint */
4879  int pos, /**< variable position */
4880  PROPRULE proprule, /**< propagation rule that deduced the value */
4881  SCIP_Real newlb, /**< new lower bound */
4882  SCIP_Real oldlb, /**< old lower bound */
4883  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4884  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4885  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4886  )
4887 {
4888  SCIP_CONSDATA* consdata;
4889  SCIP_VAR* var;
4891  SCIP_Bool infeasible;
4892  SCIP_Bool tightened;
4893 
4894  assert(cons != NULL);
4895  assert(!SCIPisInfinity(scip, newlb));
4896 
4897  consdata = SCIPconsGetData(cons);
4898  assert(consdata != NULL);
4899  var = consdata->vars[pos];
4900  assert(var != NULL);
4901 
4902  ub = SCIPvarGetUbLocal(var);
4903  newlb = SCIPadjustedVarLb(scip, var, newlb);
4904 
4905  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
4906  {
4907  SCIP_VARTYPE vartype;
4908 
4909  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
4910  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
4911 
4912  vartype = SCIPvarGetType(var);
4913 
4914  /* tighten lower bound */
4915  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
4916 
4917  if( infeasible )
4918  {
4919  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4920  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4921 
4922  /* analyze conflict */
4923  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
4924 
4925  *cutoff = TRUE;
4926  }
4927  else if( tightened )
4928  {
4929  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
4930  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4931  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
4932 
4933  (*nchgbds)++;
4934 
4935  /* if variable type was changed we might be able to upgrade the constraint */
4936  if( vartype != SCIPvarGetType(var) )
4937  consdata->upgradetried = FALSE;
4938  }
4939  }
4940  return SCIP_OKAY;
4941 }
4942 
4943 /** tightens bounds of a single variable due to activity bounds (easy case) */
4944 static
4946  SCIP* scip, /**< SCIP data structure */
4947  SCIP_CONS* cons, /**< linear constraint */
4948  int pos, /**< position of the variable in the vars array */
4949  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4950  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4951  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4952  )
4953 {
4954  SCIP_CONSDATA* consdata;
4955  SCIP_VAR* var;
4956  SCIP_Real val;
4957  SCIP_Real lb;
4958  SCIP_Real ub;
4960  SCIP_Real rhs;
4961 
4962  assert(scip != NULL);
4963  assert(cons != NULL);
4964  assert(cutoff != NULL);
4965  assert(nchgbds != NULL);
4966 
4967  /* we cannot tighten variables' bounds, if the constraint may be not complete */
4968  if( SCIPconsIsModifiable(cons) )
4969  return SCIP_OKAY;
4970 
4971  consdata = SCIPconsGetData(cons);
4972  assert(consdata != NULL);
4973  assert(0 <= pos && pos < consdata->nvars);
4974 
4975  *cutoff = FALSE;
4976 
4977  var = consdata->vars[pos];
4978  assert(var != NULL);
4979 
4980  /* we cannot tighten bounds of multi-aggregated variables */
4982  return SCIP_OKAY;
4983 
4984  val = consdata->vals[pos];
4985  lhs = consdata->lhs;
4986  rhs = consdata->rhs;
4987  assert(!SCIPisZero(scip, val));
4988  assert(!SCIPisInfinity(scip, lhs));
4989  assert(!SCIPisInfinity(scip, -rhs));
4990 
4991  lb = SCIPvarGetLbLocal(var);
4992  ub = SCIPvarGetUbLocal(var);
4993  assert(SCIPisLE(scip, lb, ub));
4994 
4995  /* recompute activities if needed */
4996  if( !consdata->validactivities )
4997  consdataCalcActivities(scip, consdata);
4998  assert(consdata->validactivities);
4999  if( !consdata->validminact )
5000  consdataRecomputeMinactivity(scip, consdata);
5001  assert(consdata->validminact);
5002  if( !consdata->validmaxact )
5003  consdataRecomputeMaxactivity(scip, consdata);
5004  assert(consdata->validmaxact);
5005 
5006  if( val > 0.0 )
5007  {
5008  /* check, if we can tighten the variable's upper bound */
5009  if( !SCIPisInfinity(scip, rhs) )
5010  {
5011  SCIP_Real slack;
5012  SCIP_Real alpha;
5013 
5014  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5015  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5016  {
5017  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5018  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5019 
5020  *cutoff = TRUE;
5021  return SCIP_OKAY;
5022  }
5023 
5024  slack = rhs - consdata->minactivity;
5025 
5026  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5027  * it to zero
5028  */
5029  if( !SCIPisPositive(scip, slack) )
5030  slack = 0.0;
5031 
5032  alpha = val * (ub - lb);
5033  assert(!SCIPisNegative(scip, alpha));
5034 
5035  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5036  {
5037  SCIP_Real newub;
5038 
5039  /* compute new upper bound */
5040  newub = lb + (slack / val);
5041 
5042  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5043 
5044  if( *cutoff )
5045  {
5046  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5047  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5048 
5049  return SCIP_OKAY;
5050  }
5051 
5052  /* collect the new upper bound which is needed for the lower bound computation */
5053  ub = SCIPvarGetUbLocal(var);
5054  }
5055  }
5056 
5057  /* check, if we can tighten the variable's lower bound */
5058  if( !SCIPisInfinity(scip, -lhs) )
5059  {
5060  SCIP_Real slack;
5061  SCIP_Real alpha;
5062 
5063  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5064  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5065  {
5066  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5067  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5068 
5069  *cutoff = TRUE;
5070  return SCIP_OKAY;
5071  }
5072 
5073  slack = consdata->maxactivity - lhs;
5074 
5075  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5076  * it to zero
5077  */
5078  if( !SCIPisPositive(scip, slack) )
5079  slack = 0.0;
5080 
5081  alpha = val * (ub - lb);
5082  assert(!SCIPisNegative(scip, alpha));
5083 
5084  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5085  {
5086  SCIP_Real newlb;
5087 
5088  /* compute new lower bound */
5089  newlb = ub - (slack / val);
5090 
5091  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5092 
5093  if( *cutoff )
5094  {
5095  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5096  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5097 
5098  return SCIP_OKAY;
5099  }
5100  }
5101  }
5102  }
5103  else
5104  {
5105  /* check, if we can tighten the variable's lower bound */
5106  if( !SCIPisInfinity(scip, rhs) )
5107  {
5108  SCIP_Real slack;
5109  SCIP_Real alpha;
5110 
5111  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5112  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5113  {
5114  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5115  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5116 
5117  *cutoff = TRUE;
5118  return SCIP_OKAY;
5119  }
5120 
5121  slack = rhs - consdata->minactivity;
5122 
5123  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5124  * it to zero
5125  */
5126  if( !SCIPisPositive(scip, slack) )
5127  slack = 0.0;
5128 
5129  alpha = val * (lb - ub);
5130  assert(!SCIPisNegative(scip, alpha));
5131 
5132  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5133  {
5134  SCIP_Real newlb;
5135 
5136  /* compute new lower bound */
5137  newlb = ub + slack / val;
5138 
5139  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5140 
5141  if( *cutoff )
5142  {
5143  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5144  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5145 
5146  return SCIP_OKAY;
5147  }
5148  /* collect the new lower bound which is needed for the upper bound computation */
5149  lb = SCIPvarGetLbLocal(var);
5150  }
5151  }
5152 
5153  /* check, if we can tighten the variable's upper bound */
5154  if( !SCIPisInfinity(scip, -lhs) )
5155  {
5156  SCIP_Real slack;
5157  SCIP_Real alpha;
5158 
5159  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5160  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5161  {
5162  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5163  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5164 
5165  *cutoff = TRUE;
5166  return SCIP_OKAY;
5167  }
5168 
5169  slack = consdata->maxactivity - lhs;
5170 
5171  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5172  * it to zero
5173  */
5174  if( !SCIPisPositive(scip, slack) )
5175  slack = 0.0;
5176 
5177  alpha = val * (lb - ub);
5178  assert(!SCIPisNegative(scip, alpha));
5179 
5180  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5181  {
5182  SCIP_Real newub;
5183 
5184  /* compute new upper bound */
5185  newub = lb - (slack / val);
5186 
5187  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5188 
5189  if( *cutoff )
5190  {
5191  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5192  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5193 
5194  return SCIP_OKAY;
5195  }
5196  }
5197  }
5198  }
5199 
5200  return SCIP_OKAY;
5201 }
5202 
5203 /** tightens bounds of a single variable due to activity bounds */
5204 static
5206  SCIP* scip, /**< SCIP data structure */
5207  SCIP_CONS* cons, /**< linear constraint */
5208  int pos, /**< position of the variable in the vars array */
5209  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5210  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5211  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5212  )
5213 {
5214  SCIP_CONSDATA* consdata;
5215  SCIP_VAR* var;
5216  SCIP_Real val;
5217  SCIP_Real lb;
5218  SCIP_Real ub;
5219  SCIP_Real minresactivity;
5220  SCIP_Real maxresactivity;
5221  SCIP_Real lhs;
5222  SCIP_Real rhs;
5223  SCIP_Bool infeasible;
5224  SCIP_Bool tightened;
5225  SCIP_Bool minisrelax;
5226  SCIP_Bool maxisrelax;
5227  SCIP_Bool isminsettoinfinity;
5228  SCIP_Bool ismaxsettoinfinity;
5229 
5230  assert(scip != NULL);
5231  assert(cons != NULL);
5232  assert(cutoff != NULL);
5233  assert(nchgbds != NULL);
5234 
5235  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5236  if( SCIPconsIsModifiable(cons) )
5237  return SCIP_OKAY;
5238 
5239  consdata = SCIPconsGetData(cons);
5240  assert(consdata != NULL);
5241  assert(0 <= pos && pos < consdata->nvars);
5242 
5243  *cutoff = FALSE;
5244 
5245  var = consdata->vars[pos];
5246 
5247  /* we cannot tighten bounds of multi-aggregated variables */
5249  return SCIP_OKAY;
5250 
5251  val = consdata->vals[pos];
5252  lhs = consdata->lhs;
5253  rhs = consdata->rhs;
5254  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
5255  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
5256  assert(var != NULL);
5257  assert(!SCIPisZero(scip, val));
5258  assert(!SCIPisInfinity(scip, lhs));
5259  assert(!SCIPisInfinity(scip, -rhs));
5260 
5261  lb = SCIPvarGetLbLocal(var);
5262  ub = SCIPvarGetUbLocal(var);
5263  assert(SCIPisLE(scip, lb, ub));
5264 
5265  if( val > 0.0 )
5266  {
5267  /* check, if we can tighten the variable's bounds */
5268  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
5269  {
5270  SCIP_Real newub;
5271 
5272  newub = (rhs - minresactivity)/val;
5273 
5274  if( !SCIPisInfinity(scip, newub) &&
5275  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
5276  {
5277  SCIP_Bool activityunreliable;
5278  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
5279 
5280  /* check minresactivities for reliability */
5281  if( activityunreliable )
5282  {
5283  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
5284  newub = (rhs - minresactivity)/val;
5285  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
5286  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
5287  && (!force || !SCIPisLT(scip, newub, ub)));
5288  }
5289 
5290  if( !activityunreliable )
5291  {
5292  /* tighten upper bound */
5293  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5294  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
5295  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
5296  &infeasible, &tightened) );
5297  if( infeasible )
5298  {
5299  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5300  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5301 
5302  /* analyze conflict */
5303  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5304 
5305  *cutoff = TRUE;
5306  return SCIP_OKAY;
5307  }
5308  if( tightened )
5309  {
5310  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5311  assert(SCIPisFeasLE(scip, ub, newub));
5312  (*nchgbds)++;
5313 
5314  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5315  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5316  }
5317  }
5318  }
5319  }
5320 
5321  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
5322  {
5323  SCIP_Real newlb;
5324 
5325  newlb = (lhs - maxresactivity)/val;
5326  if( !SCIPisInfinity(scip, -newlb) &&
5327  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
5328  {
5329  /* check maxresactivities for reliability */
5330  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
5331  {
5332  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
5333  newlb = (lhs - maxresactivity)/val;
5334 
5335  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
5336  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
5337  && (!force || !SCIPisGT(scip, newlb, lb))) )
5338  return SCIP_OKAY;
5339  }
5340 
5341  /* tighten lower bound */
5342  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5343  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
5344  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
5345  &infeasible, &tightened) );
5346  if( infeasible )
5347  {
5348  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5349  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5350 
5351  /* analyze conflict */
5352  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5353 
5354  *cutoff = TRUE;
5355  return SCIP_OKAY;
5356  }
5357  if( tightened )
5358  {
5359  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5360  assert(SCIPisFeasGE(scip, lb, newlb));
5361  (*nchgbds)++;
5362  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5363  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5364  }
5365  }
5366  }
5367  }
5368  else
5369  {
5370  /* check, if we can tighten the variable's bounds */
5371  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
5372  {
5373  SCIP_Real newlb;
5374 
5375  newlb = (rhs - minresactivity)/val;
5376  if( !SCIPisInfinity(scip, -newlb) &&
5377  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
5378  {
5379  SCIP_Bool activityunreliable;
5380  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
5381  /* check minresactivities for reliability */
5382  if( activityunreliable )
5383  {
5384  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
5385  newlb = (rhs - minresactivity)/val;
5386 
5387  activityunreliable = SCIPisInfinity(scip, -minresactivity)
5388  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
5389  && (!force || !SCIPisGT(scip, newlb, lb)));
5390  }
5391 
5392  if( !activityunreliable )
5393  {
5394  /* tighten lower bound */
5395  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5396  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
5397  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
5398  &infeasible, &tightened) );
5399  if( infeasible )
5400  {
5401  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5402  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5403 
5404  /* analyze conflict */
5405  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5406 
5407  *cutoff = TRUE;
5408  return SCIP_OKAY;
5409  }
5410  if( tightened )
5411  {
5412  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5413  assert(SCIPisFeasGE(scip, lb, newlb));
5414  (*nchgbds)++;
5415  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5416  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5417  }
5418  }
5419  }
5420  }
5421 
5422  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
5423  {
5424  SCIP_Real newub;
5425 
5426  newub = (lhs - maxresactivity)/val;
5427  if( !SCIPisInfinity(scip, newub) &&
5428  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
5429  {
5430  /* check maxresactivities for reliability */
5431  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
5432  {
5433  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
5434  newub = (lhs - maxresactivity)/val;
5435 
5436  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
5437  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
5438  && (!force || !SCIPisLT(scip, newub, ub))) )
5439  return SCIP_OKAY;
5440  }
5441 
5442  /* tighten upper bound */
5443  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
5444  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
5445  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
5446  &infeasible, &tightened) );
5447  if( infeasible )
5448  {
5449  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5450  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5451 
5452  /* analyze conflict */
5453  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5454 
5455  *cutoff = TRUE;
5456  return SCIP_OKAY;
5457  }
5458  if( tightened )
5459  {
5460  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5461  assert(SCIPisFeasLE(scip, ub, newub));
5462  (*nchgbds)++;
5463  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5464  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5465  }
5466  }
5467  }
5468  }
5469 
5470  return SCIP_OKAY;
5471 }
5472 
5473 #define MAXTIGHTENROUNDS 10
5474 #define MAXACTIVITYDELTATHR 1e6
5475 
5476 /** tightens bounds of variables in constraint due to activity bounds */
5477 static
5479  SCIP* scip, /**< SCIP data structure */
5480  SCIP_CONS* cons, /**< linear constraint */
5481  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
5482  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5483  int* nchgbds /**< pointer to count the total number of tightened bounds */
5484  )
5485 {
5486  SCIP_CONSDATA* consdata;
5487  int nvars;
5488  int nrounds;
5489  int lastchange;
5490  int oldnchgbds;
5491  int v;
5492  SCIP_Bool force;
5493  SCIP_Bool easycase;
5494 
5495  assert(scip != NULL);
5496  assert(cons != NULL);
5497  assert(nchgbds != NULL);
5498  assert(cutoff != NULL);
5499 
5500  *cutoff = FALSE;
5501 
5502  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5503  if( SCIPconsIsModifiable(cons) )
5504  return SCIP_OKAY;
5505 
5506  /* if a constraint was created after presolve, then it may hold fixed variables
5507  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
5508  * thus, ensure here again that variable fixings have been applied
5509  */
5510  SCIP_CALL( applyFixings(scip, cons, cutoff) );
5511  if( *cutoff )
5512  return SCIP_OKAY;
5513 
5514  /* check if constraint has any chances of tightening bounds */
5515  if( !canTightenBounds(scip, cons) )
5516  return SCIP_OKAY;
5517 
5518  consdata = SCIPconsGetData(cons);
5519  assert(consdata != NULL);
5520 
5521  nvars = consdata->nvars;
5522  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
5523 
5524  /* ensure that the variables are properly sorted */
5525  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
5526  {
5527  SCIP_CALL( consdataSort(scip, consdata) );
5528  assert(consdata->binvarssorted);
5529  }
5530 
5531  /* update maximal activity delta if necessary */
5532  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
5533  consdataRecomputeMaxActivityDelta(scip, consdata);
5534 
5535  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
5536  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
5537  checkMaxActivityDelta(scip, consdata);
5538 
5539  /* this may happen if all variables are fixed */
5540  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
5541  return SCIP_OKAY;
5542 
5543  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
5544  {
5545  SCIP_Real slack;
5546  SCIP_Real surplus;
5547  SCIP_Real minactivity;
5548  SCIP_Real maxactivity;
5549  SCIP_Bool minisrelax;
5550  SCIP_Bool maxisrelax;
5551 
5552  /* use maximal activity delta to skip propagation (cannot deduce anything) */
5553  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
5554  assert(!SCIPisInfinity(scip, minactivity));
5555  assert(!SCIPisInfinity(scip, -maxactivity));
5556 
5557  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
5558  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
5559 
5560  /* check if the constraint will propagate */
5561  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
5562  return SCIP_OKAY;
5563  }
5564 
5565  /* check if we can use fast implementation for easy and numerically well behaved cases */
5566  easycase = SCIPisLT(scip, consdata->maxactdelta, MAXACTIVITYDELTATHR);
5567 
5568  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
5569  lastchange = -1;
5570  for( nrounds = 0; (force || !consdata->boundstightened) && nrounds < MAXTIGHTENROUNDS; ++nrounds )
5571  {
5572  /* mark the constraint to have the variables' bounds tightened */
5573  consdata->boundstightened = TRUE;
5574 
5575  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
5576  * sorting enables skipping variables
5577  */
5578  v = 0;
5579  while( v < nvars && v != lastchange && !(*cutoff) )
5580  {
5581  oldnchgbds = *nchgbds;
5582 
5583  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
5584 
5585  if( easycase )
5586  {
5587  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
5588  }
5589  else
5590  {
5591  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
5592  }
5593 
5594  /* if there was no progress, skip the rest of the binary variables */
5595  if( *nchgbds > oldnchgbds )
5596  {
5597  lastchange = v;
5598  ++v;
5599  }
5600  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
5601  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
5602  v = consdata->nbinvars;
5603  else
5604  ++v;
5605  }
5606  }
5607 #ifndef NDEBUG
5608  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5609  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
5610 #endif
5611 
5612  return SCIP_OKAY;
5613 }
5614 
5615 /** checks linear constraint for feasibility of given solution or current solution */
5616 static
5618  SCIP* scip, /**< SCIP data structure */
5619  SCIP_CONS* cons, /**< linear constraint */
5620  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
5621  SCIP_Bool checklprows, /**< has linear constraint to be checked, if it is already in current LP? */
5622  SCIP_Bool checkrelmaxabs, /**< should the violation for a constraint with side 0.0 be checked relative
5623  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
5624  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
5625  )
5626 {
5627  SCIP_CONSDATA* consdata;
5628  SCIP_Real activity;
5629 
5630  assert(scip != NULL);
5631  assert(cons != NULL);
5632  assert(violated != NULL);
5633 
5634  SCIPdebugMessage("checking linear constraint <%s>\n", SCIPconsGetName(cons));
5635  SCIPdebugPrintCons(scip, cons, NULL);
5636 
5637  consdata = SCIPconsGetData(cons);
5638  assert(consdata != NULL);
5639 
5640  *violated = FALSE;
5641 
5642  if( consdata->row != NULL )
5643  {
5644  if( !checklprows && SCIProwIsInLP(consdata->row) )
5645  return SCIP_OKAY;
5646  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
5647  activity = consdataComputePseudoActivity(scip, consdata);
5648  else
5649  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
5650  }
5651  else
5652  activity = consdataGetActivity(scip, consdata, sol);
5653 
5654  SCIPdebugMessage(" consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
5655  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
5656  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
5657  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
5658 
5659  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
5660  * return infeasible for safety
5661  */
5662  if( activity == SCIP_INVALID ) /*lint !e777*/
5663  {
5664  assert(sol == NULL);
5665  *violated = TRUE;
5666 
5667  /* reset constraint age since we are in enforcement */
5668  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5669  }
5670  else if( SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs) )
5671  {
5672  /* the "normal" check: one of the two sides is violated */
5673  if( !checkrelmaxabs )
5674  {
5675  *violated = TRUE;
5676 
5677  /* only reset constraint age if we are in enforcement */
5678  if( sol == NULL )
5679  {
5680  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5681  }
5682  }
5683  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
5684  * small compared to the absolute values occuring in the activity
5685  */
5686  else
5687  {
5688  SCIP_Real maxabs;
5689  SCIP_Real coef;
5690  SCIP_Real absval;
5691  SCIP_Real solval;
5692  int v;
5693 
5694  maxabs = 1.0;
5695 
5696  /* compute maximum absolute value */
5697  for( v = 0; v < consdata->nvars; ++v )
5698  {
5699  if( consdata->vals != NULL )
5700  {
5701  coef = consdata->vals[v];
5702  }
5703  else
5704  coef = 1.0;
5705 
5706  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
5707  absval = REALABS( coef * solval );
5708  maxabs = MAX( maxabs, absval );
5709  }
5710 
5711  /* regard left hand side, first */
5712  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
5713  {
5714  /* check whether violation is random noise */
5715  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
5716  {
5717  SCIPdebugMessage(" lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
5718  consdata->lhs - activity, maxabs);
5719  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5720 
5721  /* only increase constraint age if we are in enforcement */
5722  if( sol == NULL )
5723  {
5724  SCIP_CALL( SCIPincConsAge(scip, cons) );
5725  }
5726  }
5727  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
5728  else if( SCIPisZero(scip, consdata->lhs) )
5729  {
5730  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
5731  {
5732  SCIPdebugMessage(" lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
5733  consdata->lhs - activity, maxabs);
5734  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5735 
5736  /* only increase constraint age if we are in enforcement */
5737  if( sol == NULL )
5738  {
5739  SCIP_CALL( SCIPincConsAge(scip, cons) );
5740  }
5741  }
5742  else
5743  {
5744  *violated = TRUE;
5745 
5746  /* only reset constraint age if we are in enforcement */
5747  if( sol == NULL )
5748  {
5749  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5750  }
5751  }
5752  }
5753  else
5754  {
5755  *violated = TRUE;
5756 
5757  /* only reset constraint age if we are in enforcement */
5758  if( sol == NULL )
5759  {
5760  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5761  }
5762  }
5763  }
5764 
5765  /* now regard right hand side */
5766  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
5767  {
5768  /* check whether violation is random noise */
5769  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
5770  {
5771  SCIPdebugMessage(" rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
5772  activity - consdata->rhs, maxabs);
5773  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5774 
5775  /* only increase constraint age if we are in enforcement */
5776  if( sol == NULL )
5777  {
5778  SCIP_CALL( SCIPincConsAge(scip, cons) );
5779  }
5780  }
5781  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
5782  else if( SCIPisZero(scip, consdata->rhs) )
5783  {
5784  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
5785  {
5786  SCIPdebugMessage(" rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
5787  activity - consdata->rhs, maxabs);
5788  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5789 
5790  /* only increase constraint age if we are in enforcement */
5791  if( sol == NULL )
5792  {
5793  SCIP_CALL( SCIPincConsAge(scip, cons) );
5794  }
5795  }
5796  else
5797  {
5798  *violated = TRUE;
5799 
5800  /* only reset constraint age if we are in enforcement */
5801  if( sol == NULL )
5802  {
5803  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5804  }
5805  }
5806  }
5807  else
5808  {
5809  *violated = TRUE;
5810 
5811  /* only reset constraint age if we are in enforcement */
5812  if( sol == NULL )
5813  {
5814  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5815  }
5816  }
5817  }
5818  }
5819  }
5820  else
5821  {
5822  /* only increase constraint age if we are in enforcement */
5823  if( sol == NULL )
5824  {
5825  SCIP_CALL( SCIPincConsAge(scip, cons) );
5826  }
5827  }
5828 
5829  return SCIP_OKAY;
5830 }
5831 
5832 /** creates an LP row in a linear constraint data */
5833 static
5835  SCIP* scip, /**< SCIP data structure */
5836  SCIP_CONS* cons /**< linear constraint */
5837  )
5838 {
5839  SCIP_CONSDATA* consdata;
5840 
5841  assert(scip != NULL);
5842  assert(cons != NULL);
5843 
5844  consdata = SCIPconsGetData(cons);
5845  assert(consdata != NULL);
5846  assert(consdata->row == NULL);
5847 
5848  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
5850 
5851  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
5852 
5853  return SCIP_OKAY;
5854 }
5855 
5856 /** adds linear constraint as cut to the LP */
5857 static
5859  SCIP* scip, /**< SCIP data structure */
5860  SCIP_CONS* cons, /**< linear constraint */
5861  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
5862  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
5863  )
5864 {
5865  SCIP_CONSDATA* consdata;
5866 
5867  assert(scip != NULL);
5868  assert(cons != NULL);
5869 
5870  consdata = SCIPconsGetData(cons);
5871  assert(consdata != NULL);
5873  if( consdata->row == NULL )
5874  {
5875  /* convert consdata object into LP row */
5876  SCIP_CALL( createRow(scip, cons) );
5877  }
5878  assert(consdata->row != NULL);
5879 
5880  /* insert LP row as cut */
5881  if( !SCIProwIsInLP(consdata->row) )
5882  {
5883  SCIPdebugMessage("adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
5884  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
5885  /* if presolving is turned off, the row might be trivial */
5886  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
5887  {
5888  SCIP_CALL( SCIPaddCut(scip, sol, consdata->row, FALSE, cutoff) );
5889  }
5890 #ifndef NDEBUG
5891  else
5892  {
5893  int r;
5894  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &r) );
5895  assert( r == 0 );
5896  }
5897 #endif
5898  }
5899 
5900  return SCIP_OKAY;
5901 }
5902 
5903 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
5904 static
5906  SCIP* scip, /**< SCIP data structure */
5907  SCIP_CONS* cons, /**< linear constraint */
5908  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
5909  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
5910  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
5911  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
5912  * the ones with non-zero dual value? */
5913  int* ncuts, /**< pointer to add up the number of found cuts */
5914  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
5915  )
5916 {
5917  SCIP_CONSDATA* consdata;
5918  SCIP_Bool violated;
5919  int oldncuts;
5920 
5921  assert(scip != NULL);
5922  assert(conshdlrdata != NULL);
5923  assert(cons != NULL);
5924  assert(cutoff != NULL);
5925 
5926  consdata = SCIPconsGetData(cons);
5927  assert(ncuts != NULL);
5928  assert(consdata != NULL);
5929 
5930  oldncuts = *ncuts;
5931  *cutoff = FALSE;
5932 
5933  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
5934 
5935  if( violated )
5936  {
5937  /* insert LP row as cut */
5938  SCIP_CALL( addRelaxation(scip, cons, sol, cutoff) );
5939  (*ncuts)++;
5940  }
5941  else if( !SCIPconsIsModifiable(cons) && separatecards )
5942  {
5943  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
5944  if( !separateall && sol == NULL )
5945  {
5946  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
5947  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
5948  {
5949  SCIP_Real dualsol;
5950 
5951  dualsol = SCIProwGetDualsol(consdata->row);
5952  if( SCIPisFeasNegative(scip, dualsol) )
5953  {
5954  if( !SCIPisInfinity(scip, consdata->rhs) )
5955  {
5956  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5957  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
5958  }
5959  }
5960  else if( SCIPisFeasPositive(scip, dualsol) )
5961  {
5962  if( !SCIPisInfinity(scip, -consdata->lhs) )
5963  {
5964  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5965  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
5966  }
5967  }
5968  }
5969  }
5970  else
5971  {
5972  if( !SCIPisInfinity(scip, consdata->rhs) )
5973  {
5974  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5975  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
5976  }
5977  if( !SCIPisInfinity(scip, -consdata->lhs) )
5978  {
5979  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5980  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
5981  }
5982  }
5983  }
5984 
5985  if( *ncuts > oldncuts )
5986  {
5987  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5988  }
5989 
5990  return SCIP_OKAY;
5991 }
5992 
5993 /** propagation method for linear constraints */
5994 static
5996  SCIP* scip, /**< SCIP data structure */
5997  SCIP_CONS* cons, /**< linear constraint */
5998  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
5999  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
6000  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6001  int* nchgbds /**< pointer to count the total number of tightened bounds */
6002  )
6003 {
6004  SCIP_CONSDATA* consdata;
6005  SCIP_Real minactivity;
6006  SCIP_Real maxactivity;
6007  SCIP_Bool minactisrelax;
6008  SCIP_Bool maxactisrelax;
6010  assert(scip != NULL);
6011  assert(cons != NULL);
6012  assert(cutoff != NULL);
6013  assert(nchgbds != NULL);
6014 
6015  /*SCIPdebugMessage("propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
6016 
6017  consdata = SCIPconsGetData(cons);
6018  assert(consdata != NULL);
6019 
6020  *cutoff = FALSE;
6021 
6022  /* check, if constraint is already propagated */
6023  if( consdata->propagated && (!tightenbounds || consdata->boundstightened) )
6024  return SCIP_OKAY;
6025 
6026  /* mark constraint as propagated */
6027  consdata->propagated = TRUE;
6028 
6029  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
6030  if( !SCIPconsIsModifiable(cons) )
6031  {
6032  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
6033  if( !SCIPinRepropagation(scip) )
6034  {
6035  SCIP_CALL( SCIPincConsAge(scip, cons) );
6036  }
6037 
6038  /* tighten the variable's bounds */
6039  if( tightenbounds )
6040  {
6041  int oldnchgbds;
6042 
6043  oldnchgbds = *nchgbds;
6044 
6045  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6046 
6047  if( *nchgbds > oldnchgbds )
6048  {
6049  SCIP_CALL( SCIPresetConsAge(scip, cons) );
6050  }
6051  }
6052 
6053  /* check constraint for infeasibility and redundancy */
6054  if( !(*cutoff) )
6055  {
6056  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
6057 
6058  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
6059  {
6060  SCIPdebugMessage("linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
6061  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
6062 
6063  /* analyze conflict */
6064  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6065 
6066  SCIP_CALL( SCIPresetConsAge(scip, cons) );
6067  *cutoff = TRUE;
6068  }
6069  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
6070  {
6071  SCIPdebugMessage("linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
6072  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
6073 
6074  /* analyze conflict */
6075  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6076 
6077  SCIP_CALL( SCIPresetConsAge(scip, cons) );
6078  *cutoff = TRUE;
6079  }
6080  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
6081  {
6082  SCIPdebugMessage("linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
6083  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
6084  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
6085  }
6086  }
6087  }
6088 
6089  return SCIP_OKAY;
6090 }
6091 
6092 
6093 /*
6094  * Presolving methods
6095  */
6096 
6097 /** converts all variables with fixed domain into FIXED variables */
6098 static
6100  SCIP* scip, /**< SCIP data structure */
6101  SCIP_CONS* cons, /**< linear constraint */
6102  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
6103  int* nfixedvars /**< pointer to count the total number of fixed variables */
6104  )
6105 {
6106  SCIP_CONSDATA* consdata;
6107  SCIP_VAR* var;
6108  SCIP_VARSTATUS varstatus;
6109  SCIP_Real lb;
6110  SCIP_Real ub;
6111  SCIP_Bool fixed;
6112  SCIP_Bool infeasible;
6113  int v;
6114 
6115  assert(scip != NULL);
6116  assert(cons != NULL);
6117  assert(cutoff != NULL);
6118  assert(nfixedvars != NULL);
6119 
6120  consdata = SCIPconsGetData(cons);
6121  assert(consdata != NULL);
6122 
6123  for( v = 0; v < consdata->nvars; ++v )
6124  {
6125  assert(consdata->vars != NULL);
6126  var = consdata->vars[v];
6127  varstatus = SCIPvarGetStatus(var);
6128 
6129  if( varstatus != SCIP_VARSTATUS_FIXED )
6130  {
6131  lb = SCIPvarGetLbGlobal(var);
6132  ub = SCIPvarGetUbGlobal(var);
6133  if( SCIPisEQ(scip, lb, ub) )
6134  {
6135  SCIP_Real fixval;
6136 
6137  fixval = SCIPselectSimpleValue(lb - 0.9 * SCIPepsilon(scip), ub + 0.9 * SCIPepsilon(scip), MAXDNOM);
6138  SCIPdebugMessage("converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
6139  SCIPvarGetName(var), lb, ub, fixval);
6140  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
6141  if( infeasible )
6142  {
6143  SCIPdebugMessage(" -> infeasible fixing\n");
6144  *cutoff = TRUE;
6145  return SCIP_OKAY;
6146  }
6147  if( fixed )
6148  (*nfixedvars)++;
6149  }
6150  }
6151  }
6152 
6153  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
6154 
6155  if( infeasible )
6156  {
6157  SCIPdebugMessage(" -> infeasible fixing\n");
6158  *cutoff = TRUE;
6159  return SCIP_OKAY;
6160  }
6161 
6162  assert(consdata->removedfixings);
6163 
6164  return SCIP_OKAY;
6165 }
6166 
6167 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
6168 
6169 /** extracts cliques of the constraint and adds them to SCIP
6170  *
6171  * The following clique extraction mechanism are implemeneted
6172  *
6173  * 1. collect binary variables and sort them in non increasing order, then
6174  *
6175  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
6176  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
6177  * condition
6178  *
6179  * minactivity + vals[i] + vals[i+1] > rhs
6180  *
6181  * and also add the binary to binary implication also for non-successive variables for which the same argument
6182  * holds
6183  *
6184  * minactivity + vals[i] + vals[j] > rhs
6185  *
6186  * 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
6187  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
6188  *
6189  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
6190  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
6191  * condition
6192  *
6193  * maxactivity + vals[i] + vals[i-1] < lhs
6194  *
6195  * and also add the binary to binary implication also for non-successive variables for which the same argument
6196  * holds
6197  *
6198  * maxactivity + vals[i] + vals[j] < lhs
6199  *
6200  * e.g. you could multiply the above example by -1
6201  *
6202  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
6203  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
6204  * condition
6205  *
6206  * minactivity - vals[i] - vals[i-1] > rhs
6207  *
6208  * and also add the binary to binary implication also for non-successive variables for which the
6209  * same argument holds
6210  *
6211  * minactivity - vals[i] - vals[j] > rhs
6212  *
6213  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
6214  * implication x1 = 0 => x3 = 1
6215  *
6216  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
6217  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
6218  * condition
6219  *
6220  * maxactivity - vals[i] - vals[i+1] < lhs
6221  *
6222  * and also add the binary to binary implication also for non-successive variables for which the same argument
6223  * holds
6224  *
6225  * maxactivity - vals[i] - vals[j] < lhs
6226  *
6227  * e.g. you could multiply the above example by -1
6228  *
6229  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
6230  * as clique, (this part is done at the end of the method)
6231  *
6232  */
6233 static
6235  SCIP* scip, /**< SCIP data structure */
6236  SCIP_CONS* cons, /**< linear constraint */
6237  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6238  int* nfixedvars, /**< pointer to count number of fixed variables */
6239  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6240  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
6241  )
6242 {
6243  SCIP_VAR** vars;
6244  SCIP_Real* vals;
6245  SCIP_CONSDATA* consdata;
6246  SCIP_Bool lhsclique;
6247  SCIP_Bool rhsclique;
6248  SCIP_Bool finitelhs;
6249  SCIP_Bool finiterhs;
6250  SCIP_Bool finiteminact;
6251  SCIP_Bool finitemaxact;
6252  SCIP_Bool finitenegminact;
6253  SCIP_Bool finitenegmaxact;
6254  SCIP_Bool finiteposminact;
6255  SCIP_Bool finiteposmaxact;
6256  SCIP_Bool infeasible;
6257  SCIP_Bool stopped;
6258  int cliquenonzerosadded;
6259  int v;
6260  int i;
6261  int nposcoefs;
6262  int nnegcoefs;
6263  int nvars;
6264 
6265  assert(scip != NULL);
6266  assert(cons != NULL);
6267  assert(nfixedvars != NULL);
6268  assert(nchgbds != NULL);
6269  assert(cutoff != NULL);
6270  assert(!SCIPconsIsDeleted(cons));
6271 
6272  consdata = SCIPconsGetData(cons);
6273  assert(consdata != NULL);
6274 
6275  if( consdata->nvars < 2 )
6276  return SCIP_OKAY;
6277 
6278  /* add implications if posibble
6279  *
6280  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
6281  * maximal absolute contribution and also only if this variable would force all other variables to their bound
6282  * corresponding to the global minimal activity of the constraint
6283  */
6284  if( !consdata->implsadded )
6285  {
6286  /* sort variables by variable type */
6287  SCIP_CALL( consdataSort(scip, consdata) );
6288 
6289  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
6290  * up front, might change sorting correspondingly
6291  */
6292  /* fast abort if no binaries exist */
6293  if( !SCIPvarIsBinary(consdata->vars[0]) )
6294  return SCIP_OKAY;
6295 
6296  nvars = consdata->nvars;
6297  vars = consdata->vars;
6298  vals = consdata->vals;
6299 
6300  /* recompute activities if needed */
6301  if( !consdata->validactivities )
6302  consdataCalcActivities(scip, consdata);
6303  assert(consdata->validactivities);
6304 
6305  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
6306  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
6307  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
6308  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
6309  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
6310  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
6311  finiteminact = (finitenegminact && finiteposminact);
6312  finitemaxact = (finitenegmaxact && finiteposmaxact);
6313 
6314  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
6315  {
6316  SCIP_Real maxabscontrib = -1.0;
6317  SCIP_Bool posval = FALSE;
6318  SCIP_Bool allbinary = TRUE;
6319  int oldnchgbds = *nchgbds;
6320  int nbdchgs = 0;
6321  int nimpls = 0;
6322  int position = -1;
6323 
6324  /* we need a valid minimal/maximal activity to add cliques */
6325  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
6326  {
6327  consdataRecomputeGlbMinactivity(scip, consdata);
6328  assert(consdata->validglbminact);
6329  }
6330 
6331  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
6332  {
6333  consdataRecomputeGlbMaxactivity(scip, consdata);
6334  assert(consdata->validglbmaxact);
6335  }
6336  assert(consdata->validglbminact || consdata->validglbmaxact);
6337 
6338  /* @todo extend this to local/constraint probing */
6339 
6340  /* determine maximal contribution to the activity */
6341  for( v = nvars - 1; v >= 0; --v )
6342  {
6343  if( SCIPvarIsBinary(vars[v]) )
6344  {
6345  if( vals[v] > 0 )
6346  {
6347  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
6348 
6349  if( value > maxabscontrib )
6350  {
6351  maxabscontrib = value;
6352  position = v;
6353  posval = TRUE;
6354  }
6355  }
6356  else
6357  {
6358  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
6359 
6360  value = REALABS(value);
6361 
6362  if( value > maxabscontrib )
6363  {
6364  maxabscontrib = value;
6365  position = v;
6366  posval = FALSE;
6367  }
6368  }
6369  }
6370  else
6371  allbinary = FALSE;
6372  }
6373  assert(0 <= position && position < nvars);
6374 
6375  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
6376  {
6377  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
6378  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
6379  * implications
6380  */
6381  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
6382  {
6383  for( v = nvars - 1; v >= 0; --v )
6384  {
6385  /* binary to binary implications will be collected when extrating cliques */
6386  if( !SCIPvarIsBinary(vars[v]) )
6387  {
6388  if( v != position )
6389  {
6390  if( vals[v] > 0 )
6391  {
6392  /* add implications */
6393  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
6394  ++nimpls;
6395  *nchgbds += nbdchgs;
6396  }
6397  else
6398  {
6399  /* add implications */
6400  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
6401  ++nimpls;
6402  *nchgbds += nbdchgs;
6403  }
6404 
6405  if( infeasible )
6406  {
6407  *cutoff = TRUE;
6408  break;
6409  }
6410  }
6411  }
6412  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
6413  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
6414  break;
6415  }
6416  }
6417 
6418  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
6419  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
6420  * implications
6421  */
6422  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
6423  {
6424  for( v = nvars - 1; v >= 0; --v )
6425  {
6426  /* binary to binary implications will be collected when extrating cliques */
6427  if( !SCIPvarIsBinary(vars[v]) )
6428  {
6429  if( v != position )
6430  {
6431  if( vals[v] > 0 )
6432  {
6433  /* add implications */
6434  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
6435  ++nimpls;
6436  *nchgbds += nbdchgs;
6437  }
6438  else
6439  {
6440  /* add implications */
6441  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
6442  ++nimpls;
6443  *nchgbds += nbdchgs;
6444  }
6445 
6446  if( infeasible )
6447  {
6448  *cutoff = TRUE;
6449  break;
6450  }
6451  }
6452  }
6453  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
6454  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
6455  break;
6456  }
6457  }
6458 
6459  /* did we find some implications */
6460  if( nimpls > 0 )
6461  {
6462  SCIPdebugMessage("extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
6463 
6464  if( *cutoff )
6465  return SCIP_OKAY;
6466 
6467  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6468  if( *nchgbds - oldnchgbds > 0 )
6469  {
6470  /* check for fixed variables */
6471  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6472  if( *cutoff )
6473  return SCIP_OKAY;
6474 
6475  /* tighten variable's bounds */
6476  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6477  if( *cutoff )
6478  return SCIP_OKAY;
6479 
6480  /* check for fixed variables */
6481  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6482  if( *cutoff )
6483  return SCIP_OKAY;
6484  }
6485  }
6486  }
6487  }
6488 
6489  consdata->implsadded = TRUE;
6490  }
6491 
6492  /* check if we already added the cliques of this constraint */
6493  if( consdata->cliquesadded )
6494  return SCIP_OKAY;
6495 
6496  consdata->cliquesadded = TRUE;
6497  cliquenonzerosadded = 0;
6498  stopped = FALSE;
6499 
6500  /* sort variables by variable type */
6501  SCIP_CALL( consdataSort(scip, consdata) );
6502 
6503  nvars = consdata->nvars;
6504  vars = consdata->vars;
6505  vals = consdata->vals;
6506 
6507  /**@todo extract more cliques, implications and variable bounds from linear constraints */
6508 
6509  /* recompute activities if needed */
6510  if( !consdata->validactivities )
6511  consdataCalcActivities(scip, consdata);
6512  assert(consdata->validactivities);
6513 
6514  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
6515  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
6516  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
6517  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
6518  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
6519  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
6520  finiteminact = (finitenegminact && finiteposminact);
6521  finitemaxact = (finitenegmaxact && finiteposmaxact);
6522 
6523  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
6524  * information
6525  */
6526  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
6527  {
6528  SCIP_VAR** binvars;
6529  SCIP_Real* binvarvals;
6530  int nposbinvars = 0;
6531  int nnegbinvars = 0;
6532  int allonebinary = 0;
6533 
6534  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
6535  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
6536 
6537  /* collect binary variables */
6538  for( i = 0; i < nvars; ++i )
6539  {
6540  if( SCIPvarIsBinary(vars[i]) )
6541  {
6542  assert(!SCIPisZero(scip, vals[i]));
6543 
6544  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6545  ++allonebinary;
6546 
6547  binvars[nposbinvars + nnegbinvars] = vars[i];
6548  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6549 
6550  if( SCIPisPositive(scip, vals[i]) )
6551  ++nposbinvars;
6552  else
6553  ++nnegbinvars;
6554 
6555  assert(nposbinvars + nnegbinvars <= nvars);
6556  }
6557  /* stop searching for binary variables, because the constraint data is sorted */
6558  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6559  break;
6560  }
6561  assert(nposbinvars + nnegbinvars <= nvars);
6562 
6563  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
6564  * cliques
6565  */
6566  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
6567  {
6568  SCIP_Real threshold;
6569  int oldnchgbds = *nchgbds;
6570  int nbdchgs;
6571  int jstart;
6572  int j;
6573 
6574  /* we need a valid minimal/maximal activity to add cliques */
6575  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
6576  {
6577  consdataRecomputeGlbMinactivity(scip, consdata);
6578  assert(consdata->validglbminact);
6579  }
6580 
6581  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
6582  {
6583  consdataRecomputeGlbMaxactivity(scip, consdata);
6584  assert(consdata->validglbmaxact);
6585  }
6586  assert(consdata->validglbminact || consdata->validglbmaxact);
6587 
6588  /* sort coefficients non-increasing to be faster in the clique search */
6589  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
6590 
6591  /* case a) */
6592  if( finiterhs && finitenegminact && nposbinvars >= 2 )
6593  {
6594  /* compute value that needs to be exceeded */
6595  threshold = consdata->rhs - consdata->glbminactivity;
6596 
6597  i = 0;
6598  j = i + 1;
6599 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6600  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
6601  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
6602 #endif
6603  /* check if at least two variables are in a clique */
6604  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
6605  {
6606  ++j;
6607  /* check for extending the clique */
6608  while( j < nposbinvars )
6609  {
6610  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
6611  break;
6612  ++j;
6613  }
6614  assert(j >= 2);
6615 
6616  /* add clique with at least two variables */
6617  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, &infeasible, &nbdchgs) );
6618 
6619  if( infeasible )
6620  *cutoff = TRUE;
6621 
6622  *nchgbds += nbdchgs;
6623 
6624  cliquenonzerosadded += j;
6625  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6626  stopped = TRUE;
6627 
6628  /* exchange the last variable in the clique if possible and add all new ones */
6629  if( !stopped && !(*cutoff) && j < nposbinvars )
6630  {
6631  SCIP_VAR** clqvars;
6632  int lastfit = j - 2;
6633  assert(lastfit >= i);
6634 
6635  /* copy all 'main'-clique variables */
6636  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
6637 
6638  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
6639  while( lastfit >= i && j < nposbinvars )
6640  {
6641  /* check if two variables are in a clique */
6642  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
6643  {
6644  clqvars[lastfit + 1] = binvars[j];
6645 
6646  /* add clique with at least two variables */
6647  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, &infeasible, &nbdchgs) );
6648 
6649  if( infeasible )
6650  {
6651  *cutoff = TRUE;
6652  break;
6653  }
6654 
6655  *nchgbds += nbdchgs;
6656 
6657  cliquenonzerosadded += (lastfit - i + 2);
6658  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6659  {
6660  stopped = TRUE;
6661  break;
6662  }
6663 
6664  ++j;
6665  }
6666  else
6667  --lastfit;
6668  }
6669 
6670  SCIPfreeBufferArray(scip, &clqvars);
6671  }
6672  }
6673  }
6674 
6675  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6676  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6677  {
6678  /* check for fixed variables */
6679  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6680 
6681  if( !*cutoff )
6682  {
6683  /* tighten variable's bounds */
6684  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6685 
6686  if( !*cutoff )
6687  {
6688  /* check for fixed variables */
6689  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6690 
6691  if( !*cutoff )
6692  {
6693  /* sort variables by variable type */
6694  SCIP_CALL( consdataSort(scip, consdata) );
6695 
6696  /* recompute activities if needed */
6697  if( !consdata->validactivities )
6698  consdataCalcActivities(scip, consdata);
6699  assert(consdata->validactivities);
6700 
6701  nvars = consdata->nvars;
6702  vars = consdata->vars;
6703  vals = consdata->vals;
6704  nposbinvars = 0;
6705  nnegbinvars = 0;
6706  allonebinary = 0;
6707 
6708  /* update binary variables */
6709  for( i = 0; i < nvars; ++i )
6710  {
6711  if( SCIPvarIsBinary(vars[i]) )
6712  {
6713  assert(!SCIPisZero(scip, vals[i]));
6714 
6715  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6716  ++allonebinary;
6717 
6718  binvars[nposbinvars + nnegbinvars] = vars[i];
6719  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6720 
6721  if( SCIPisPositive(scip, vals[i]) )
6722  ++nposbinvars;
6723  else
6724  ++nnegbinvars;
6725 
6726  assert(nposbinvars + nnegbinvars <= nvars);
6727  }
6728  /* stop searching for binary variables, because the constraint data is sorted */
6729  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6730  break;
6731  }
6732  assert(nposbinvars + nnegbinvars <= nvars);
6733  }
6734  }
6735  }
6736 
6737  oldnchgbds = *nchgbds;
6738  }
6739 
6740  /* case b) */
6741  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
6742  {
6743  /* compute value that needs to be deceeded */
6744  threshold = consdata->lhs - consdata->glbmaxactivity;
6745 
6746  i = nposbinvars + nnegbinvars - 1;
6747  j = i - 1;
6748 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6749  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
6750  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
6751 #endif
6752  /* check if two variables are in a clique */
6753  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
6754  {
6755  --j;
6756  /* check for extending the clique */
6757  while( j >= nposbinvars )
6758  {
6759  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
6760  break;
6761  --j;
6762  }
6763  jstart = j;
6764 
6765  assert(i - j >= 2);
6766  /* add clique with at least two variables */
6767  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, &infeasible, &nbdchgs) );
6768 
6769  if( infeasible )
6770  *cutoff = TRUE;
6771 
6772  *nchgbds += nbdchgs;
6773 
6774  cliquenonzerosadded += (i - j);
6775  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6776  stopped = TRUE;
6777 
6778  /* exchange the last variable in the clique if possible and add all new ones */
6779  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
6780  {
6781  SCIP_VAR** clqvars;
6782  int lastfit = jstart + 1;
6783  assert(lastfit < i);
6784 
6785  /* copy all 'main'-clique variables */
6786  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
6787  ++lastfit;
6788 
6789  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
6790  while( lastfit <= i && j >= nposbinvars )
6791  {
6792  /* check if two variables are in a clique */
6793  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
6794  {
6795  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
6796  clqvars[lastfit - jstart - 2] = binvars[j];
6797 
6798  assert(i - lastfit + 2 >= 2);
6799  /* add clique with at least two variables */
6800  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, &infeasible, &nbdchgs) );
6801 
6802  if( infeasible )
6803  {
6804  *cutoff = TRUE;
6805  break;
6806  }
6807 
6808  *nchgbds += nbdchgs;
6809 
6810  cliquenonzerosadded += (i - lastfit + 2);
6811  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6812  {
6813  stopped = TRUE;
6814  break;
6815  }
6816 
6817  --j;
6818  }
6819  else
6820  ++lastfit;
6821  }
6822 
6823  SCIPfreeBufferArray(scip, &clqvars);
6824  }
6825  }
6826  }
6827 
6828  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6829  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6830  {
6831  /* check for fixed variables */
6832  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6833 
6834  if( !*cutoff )
6835  {
6836  /* tighten variable's bounds */
6837  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6838 
6839  if( !*cutoff )
6840  {
6841  /* check for fixed variables */
6842  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6843 
6844  if( !*cutoff )
6845  {
6846  /* sort variables by variable type */
6847  SCIP_CALL( consdataSort(scip, consdata) );
6848 
6849  /* recompute activities if needed */
6850  if( !consdata->validactivities )
6851  consdataCalcActivities(scip, consdata);
6852  assert(consdata->validactivities);
6853 
6854  nvars = consdata->nvars;
6855  vars = consdata->vars;
6856  vals = consdata->vals;
6857  nposbinvars = 0;
6858  nnegbinvars = 0;
6859  allonebinary = 0;
6860 
6861  /* update binary variables */
6862  for( i = 0; i < nvars; ++i )
6863  {
6864  if( SCIPvarIsBinary(vars[i]) )
6865  {
6866  assert(!SCIPisZero(scip, vals[i]));
6867 
6868  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6869  ++allonebinary;
6870 
6871  binvars[nposbinvars + nnegbinvars] = vars[i];
6872  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6873 
6874  if( SCIPisPositive(scip, vals[i]) )
6875  ++nposbinvars;
6876  else
6877  ++nnegbinvars;
6878 
6879  assert(nposbinvars + nnegbinvars <= nvars);
6880  }
6881  /* stop searching for binary variables, because the constraint data is sorted */
6882  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6883  break;
6884  }
6885  assert(nposbinvars + nnegbinvars <= nvars);
6886  }
6887  }
6888  }
6889 
6890  oldnchgbds = *nchgbds;
6891  }
6892 
6893  /* case c) */
6894  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
6895  {
6896  SCIP_Bool* values;
6897 
6898  /* initialize clique values array for adding a negated clique */
6899  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
6900  BMSclearMemoryArray(values, nnegbinvars);
6901 
6902  /* compute value that needs to be exceeded */
6903  threshold = consdata->rhs - consdata->glbminactivity;
6904 
6905  i = nposbinvars + nnegbinvars - 1;
6906  j = i - 1;
6907 
6908 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6909  /* check if the variable should not have already been fixed to one */
6910  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
6911 #endif
6912 
6913  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
6914  {
6915  --j;
6916  /* check for extending the clique */
6917  while( j >= nposbinvars )
6918  {
6919  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
6920  break;
6921  --j;
6922  }
6923  jstart = j;
6924 
6925  assert(i - j >= 2);
6926  /* add negated clique with at least two variables */
6927  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, &infeasible, &nbdchgs) );
6928 
6929  if( infeasible )
6930  *cutoff = TRUE;
6931 
6932  *nchgbds += nbdchgs;
6933 
6934  cliquenonzerosadded += (i - j);
6935  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6936  stopped = TRUE;
6937 
6938  /* exchange the last variable in the clique if possible and add all new ones */
6939  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
6940  {
6941  SCIP_VAR** clqvars;
6942  int lastfit = j + 1;
6943  assert(lastfit < i);
6944 
6945  /* copy all 'main'-clique variables */
6946  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
6947  ++lastfit;
6948 
6949  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
6950  while( lastfit <= i && j >= nposbinvars )
6951  {
6952  /* check if two variables are in a negated clique */
6953  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
6954  {
6955  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
6956  clqvars[lastfit - jstart - 2] = binvars[j];
6957 
6958  assert(i - lastfit + 2 >= 2);
6959  /* add clique with at least two variables */
6960  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, &infeasible, &nbdchgs) );
6961 
6962  if( infeasible )
6963  {
6964  *cutoff = TRUE;
6965  break;
6966  }
6967 
6968  *nchgbds += nbdchgs;
6969 
6970  cliquenonzerosadded += (i - lastfit + 2);
6971  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6972  {
6973  stopped = TRUE;
6974  break;
6975  }
6976 
6977  --j;
6978  }
6979  else
6980  ++lastfit;
6981  }
6982 
6983  SCIPfreeBufferArray(scip, &clqvars);
6984  }
6985  }
6986 
6987  SCIPfreeBufferArray(scip, &values);
6988  }
6989 
6990  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6991  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6992  {
6993  /* check for fixed variables */
6994  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6995 
6996  if( !*cutoff )
6997  {
6998  /* tighten variable's bounds */
6999  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
7000 
7001  if( !*cutoff )
7002  {
7003  /* check for fixed variables */
7004  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
7005 
7006  if( !*cutoff )
7007  {
7008  /* sort variables by variable type */
7009  SCIP_CALL( consdataSort(scip, consdata) );
7010 
7011  /* recompute activities if needed */
7012  if( !consdata->validactivities )
7013  consdataCalcActivities(scip, consdata);
7014  assert(consdata->validactivities);
7015 
7016  nvars = consdata->nvars;
7017  vars = consdata->vars;
7018  vals = consdata->vals;
7019  nposbinvars = 0;
7020  nnegbinvars = 0;
7021  allonebinary = 0;
7022 
7023  /* update binary variables */
7024  for( i = 0; i < nvars; ++i )
7025  {
7026  if( SCIPvarIsBinary(vars[i]) )
7027  {
7028  assert(!SCIPisZero(scip, vals[i]));
7029 
7030  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
7031  ++allonebinary;
7032 
7033  binvars[nposbinvars + nnegbinvars] = vars[i];
7034  binvarvals[nposbinvars + nnegbinvars] = vals[i];
7035 
7036  if( SCIPisPositive(scip, vals[i]) )
7037  ++nposbinvars;
7038  else
7039  ++nnegbinvars;
7040 
7041  assert(nposbinvars + nnegbinvars <= nvars);
7042  }
7043  /* stop searching for binary variables, because the constraint data is sorted */
7044  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
7045  break;
7046  }
7047  assert(nposbinvars + nnegbinvars <= nvars);
7048  }
7049  }
7050  }
7051  }
7052 
7053  /* case d) */
7054  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
7055  {
7056  SCIP_Bool* values;
7057 
7058  /* initialize clique values array for adding a negated clique */
7059  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
7060  BMSclearMemoryArray(values, nposbinvars);
7061 
7062  /* compute value that needs to be exceeded */
7063  threshold = consdata->lhs - consdata->glbmaxactivity;
7064 
7065  i = 0;
7066  j = i + 1;
7067 
7068 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
7069  /* check if the variable should not have already been fixed to one */
7070  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
7071 #endif
7072 
7073  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
7074  {
7075  ++j;
7076  /* check for extending the clique */
7077  while( j < nposbinvars )
7078  {
7079  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
7080  break;
7081  ++j;
7082  }
7083  assert(j >= 2);
7084 
7085  /* add negated clique with at least two variables */
7086  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, &infeasible, &nbdchgs) );
7087 
7088  if( infeasible )
7089  *cutoff = TRUE;
7090 
7091  *nchgbds += nbdchgs;
7092 
7093  cliquenonzerosadded += j;
7094  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
7095  stopped = TRUE;
7096 
7097  /* exchange the last variable in the clique if possible and add all new ones */
7098  if( !stopped && !(*cutoff) && j < nposbinvars )
7099  {
7100  SCIP_VAR** clqvars;
7101  int lastfit = j - 2;
7102  assert(lastfit >= i);
7103 
7104  /* copy all 'main'-clique variables */
7105  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
7106 
7107  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
7108  while( lastfit >= i && j < nposbinvars )
7109  {
7110  /* check if two variables are in a negated clique */
7111  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
7112  {
7113  clqvars[lastfit + 1] = binvars[j];
7114 
7115  /* add clique with at least two variables */
7116  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, &infeasible, &nbdchgs) );
7117 
7118  if( infeasible )
7119  {
7120  *cutoff = TRUE;
7121  break;
7122  }
7123 
7124  *nchgbds += nbdchgs;
7125 
7126  cliquenonzerosadded += (lastfit - i + 2);
7127  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
7128  break;
7129 
7130  ++j;
7131  }
7132  else
7133  --lastfit;
7134  }
7135 
7136  SCIPfreeBufferArray(scip, &clqvars);
7137  }
7138  }
7139 
7140  SCIPfreeBufferArray(scip, &values);
7141  }
7142  }
7143 
7144  SCIPfreeBufferArray(scip, &binvarvals);
7145  SCIPfreeBufferArray(scip, &binvars);
7146 
7147  if( *cutoff )
7148  return SCIP_OKAY;
7149  }
7150 
7151  /* 2. we only check if the constraint is a set packing / partitioning constraint */
7152 
7153  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
7154  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
7155  */
7156  nposcoefs = 0;
7157  nnegcoefs = 0;
7158  for( i = 0; i < nvars; ++i )
7159  {
7160  if( !SCIPvarIsBinary(vars[i]) )
7161  return SCIP_OKAY;
7162  else if( SCIPisEQ(scip, vals[i], +1.0) )
7163  nposcoefs++;
7164  else if( SCIPisEQ(scip, vals[i], -1.0) )
7165  nnegcoefs++;
7166  else
7167  return SCIP_OKAY;
7168  }
7169 
7170  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
7171  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
7172 
7173  if( lhsclique || rhsclique )
7174  {
7175  SCIP_Bool* values;
7176  int nbdchgs;
7177 
7178  SCIPdebugMessage("linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
7179  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
7180  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
7181 
7182  for( i = 0; i < nvars; ++i )
7183  values[i] = (rhsclique == (vals[i] > 0.0));
7184 
7185  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, &infeasible, &nbdchgs) );
7186 
7187  if( infeasible )
7188  *cutoff = TRUE;
7189 
7190  *nchgbds += nbdchgs;
7191  SCIPfreeBufferArray(scip, &values);
7192  }
7193 
7194  return SCIP_OKAY;
7195 }
7196 
7197 /** tightens left and right hand side of constraint due to integrality */
7198 static
7200  SCIP* scip, /**< SCIP data structure */
7201  SCIP_CONS* cons, /**< linear constraint */
7202  int* nchgsides /**< pointer to count number of side changes */
7203  )
7204 {
7205  SCIP_CONSDATA* consdata;
7206  SCIP_Bool integral;
7207  int i;
7208 
7209  assert(scip != NULL);
7210  assert(cons != NULL);
7211  assert(nchgsides != NULL);
7212 
7213  consdata = SCIPconsGetData(cons);
7214  assert(consdata != NULL);
7215 
7216  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
7217  {
7218  integral = TRUE;
7219  for( i = 0; i < consdata->nvars && integral; ++i )
7220  {
7221  integral = SCIPisIntegral(scip, consdata->vals[i])
7222  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
7223  }
7224  if( integral )
7225  {
7226  SCIPdebugMessage("linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
7227  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
7228  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
7229  {
7230  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
7231  if( !consdata->upgraded )
7232  (*nchgsides)++;
7233  }
7234  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
7235  {
7236  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
7237  if( !consdata->upgraded )
7238  (*nchgsides)++;
7239  }
7240  SCIPdebugMessage("linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
7241  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
7242  }
7243  }
7244 
7245  return SCIP_OKAY;
7246 }
7247 
7248 #define MAXVALRECOMP 1e+06
7249 
7250 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
7251  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
7252  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
7253  * (i) ai >= 0:
7254  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
7255  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
7256  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
7257  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
7258  * - change coefficients:
7259  * ai' := max(lhs - minact, maxact - rhs)
7260  * lhs' := lhs - (ai - ai')*li
7261  * rhs' := rhs - (ai - ai')*ui
7262  * (ii) ai < 0:
7263  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
7264  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
7265  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
7266  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
7267  * - change coefficients:
7268  * ai' := min(rhs - maxact, minact - lhs)
7269  * lhs' := lhs - (ai - ai')*ui
7270  * rhs' := rhs - (ai - ai')*li
7271  *
7272  * We further try to remove redundant variable from the constraint;
7273  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
7274  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
7275  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
7276  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
7277  * 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
7278  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
7279  *
7280  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
7281  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
7282  */
7283 static
7285  SCIP* scip, /**< SCIP data structure */
7286  SCIP_CONS* cons, /**< linear constraint */
7287  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
7288  int* nchgsides /**< pointer to count number of side changes */
7289  )
7290 {
7291  SCIP_CONSDATA* consdata;
7292  SCIP_VAR* var;
7293  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
7294  * activity, ignoring the coefficients contributing with infinite value */
7295  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
7296  * activity, ignoring the coefficients contributing with infinite value */
7297  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
7298  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
7299  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
7300  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
7301  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
7302  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
7303  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
7304  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
7305  SCIP_Real val;
7306  SCIP_Real newval;
7307  SCIP_Real newlhs;
7308  SCIP_Real newrhs;
7309  SCIP_Real lb;
7310  SCIP_Real ub;
7311  int i;
7312 
7313  assert(scip != NULL);
7314  assert(cons != NULL);
7315  assert(nchgcoefs != NULL);
7316  assert(nchgsides != NULL);
7317 
7318  consdata = SCIPconsGetData(cons);
7319  assert(consdata != NULL);
7320 
7321  /* @todo Is this still needed with automatic recomputation of activities? */
7322  /* if the maximal coefficient is too large, recompute the activities */
7323  if( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
7324  {
7325  consdataRecomputeMinactivity(scip, consdata);
7326  consdataRecomputeMaxactivity(scip, consdata);
7327  }
7328 
7329  /* get the minimal and maximal activity of the constraint */
7330  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7331 
7332  minleftactivity = 0.0;
7333  maxleftactivity = 0.0;
7334 
7335  /* try to tighten each coefficient */
7336  i = 0;
7337  while( i < consdata->nvars )
7338  {
7339  var = consdata->vars[i];
7340 
7341  /* get coefficient and variable's bounds */
7342  lb = SCIPvarGetLbLocal(var);
7343  ub = SCIPvarGetUbLocal(var);
7344  val = consdata->vals[i];
7345  assert(!SCIPisZero(scip, val));
7346 
7347  /* check sign of coefficient */
7348  if( val >= 0.0 )
7349  {
7350  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
7352  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
7353  {
7354  /* change coefficients:
7355  * ai' := max(lhs - minact, maxact - rhs)
7356  * lhs' := lhs - (ai - ai')*li
7357  * rhs' := rhs - (ai - ai')*ui
7358  */
7359 
7360  lval = consdata->lhs - minactivity;
7361  rval = maxactivity - consdata->rhs;
7362 
7363  /* Try to avoid cancellation, if there are only two variables */
7364  if( consdata->nvars == 2 )
7365  {
7366  SCIP_Real otherval;
7367  otherval = consdata->vals[1-i];
7368 
7369  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
7370  {
7371  lval = consdata->lhs - val*lb;
7372  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
7373  }
7374 
7375  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
7376  {
7377  rval = val*ub - consdata->rhs;
7378  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
7379  }
7380  }
7381 
7382  newval = MAX(lval, rval);
7383  assert(SCIPisSumRelLE(scip, newval, val));
7384 
7385  /* Try to avoid cancellation in computation of lhs/rhs */
7386  newlhs = consdata->lhs - val * lb;
7387  newlhs += newval * lb;
7388  newrhs = consdata->rhs - val * ub;
7389  newrhs += newval * ub;
7390 
7391  if( !SCIPisSumRelEQ(scip, newval, val) )
7392  {
7393  SCIPdebugMessage("linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
7394  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
7395  minactivity, maxactivity, consdata->lhs, consdata->rhs);
7396 
7397  /* update the coefficient and the activity bounds */
7398  if( SCIPisZero(scip, newval) )
7399  {
7400  SCIP_CALL( delCoefPos(scip, cons, i) );
7401  i--;
7402  }
7403  else
7404  {
7405  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
7406  }
7407  (*nchgcoefs)++;
7408 
7409  /* get the new minimal and maximal activity of the constraint */
7410  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7411 
7412  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
7413  {
7414  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7415 
7416  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7417  (*nchgsides)++;
7418  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7419  }
7420 
7421  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
7422  {
7423  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7424 
7425  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7426  (*nchgsides)++;
7427  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7428  }
7429  }
7430  }
7431  else
7432  {
7433  if( !SCIPisInfinity(scip, -minleftactivity) )
7434  {
7435  assert(!SCIPisInfinity(scip, val));
7436  assert(!SCIPisInfinity(scip, lb));
7437  if( SCIPisInfinity(scip, -lb) )
7438  minleftactivity = -SCIPinfinity(scip);
7439  else
7440  minleftactivity += val * lb;
7441  }
7442 
7443  if( !SCIPisInfinity(scip, maxleftactivity) )
7444  {
7445  assert(!SCIPisInfinity(scip, val));
7446  assert(!SCIPisInfinity(scip, -ub));
7447  if( SCIPisInfinity(scip,ub) )
7448  maxleftactivity = SCIPinfinity(scip);
7449  else
7450  maxleftactivity += val * ub;
7451  }
7452  }
7453  }
7454  else
7455  {
7456  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
7458  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
7459  {
7460  /* change coefficients:
7461  * ai' := min(rhs - maxact, minact - lhs)
7462  * lhs' := lhs - (ai - ai')*ui
7463  * rhs' := rhs - (ai - ai')*li
7464  */
7465 
7466  lval = minactivity - consdata->lhs;
7467  rval = consdata->rhs - maxactivity;
7468 
7469  /* Try to avoid cancellation, if there are only two variables */
7470  if( consdata->nvars == 2 )
7471  {
7472  SCIP_Real otherval;
7473  otherval = consdata->vals[1-i];
7474 
7475  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
7476  {
7477  lval = val*ub - consdata->lhs;
7478  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
7479  }
7480 
7481  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
7482  {
7483  rval = consdata->rhs - val*lb;
7484  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
7485  }
7486  }
7487 
7488  newval = MIN(lval, rval);
7489  assert(SCIPisSumRelGE(scip, newval, val));
7490 
7491  /* Try to avoid cancellation in computation of lhs/rhs */
7492  newlhs = consdata->lhs - val * ub;
7493  newlhs += newval * ub;
7494  newrhs = consdata->rhs - val * lb;
7495  newrhs += newval * lb;
7496 
7497  if( !SCIPisSumRelEQ(scip, newval, val) )
7498  {
7499  SCIPdebugMessage("linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
7500  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
7501  minactivity, maxactivity, consdata->lhs, consdata->rhs);
7502 
7503  /* update the coefficient and the activity bounds */
7504  if( SCIPisZero(scip, newval) )
7505  {
7506  SCIP_CALL( delCoefPos(scip, cons, i) );
7507  i--;
7508  }
7509  else
7510  {
7511  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
7512  }
7513  (*nchgcoefs)++;
7514 
7515  /* get the new minimal and maximal activity of the constraint */
7516  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7517 
7518  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
7519  {
7520  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7521 
7522  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7523  (*nchgsides)++;
7524  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7525  }
7526 
7527  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
7528  {
7529  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7530 
7531  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7532  (*nchgsides)++;
7533  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7534  }
7535  }
7536  }
7537  else
7538  {
7539  if( !SCIPisInfinity(scip, -minleftactivity) )
7540  {
7541  assert(!SCIPisInfinity(scip, -val));
7542  assert(!SCIPisInfinity(scip, -ub));
7543  if( SCIPisInfinity(scip, ub) )
7544  minleftactivity = -SCIPinfinity(scip);
7545  else
7546  minleftactivity += val * ub;
7547  }
7548 
7549  if( !SCIPisInfinity(scip, maxleftactivity) )
7550  {
7551  assert(!SCIPisInfinity(scip, -val));
7552  assert(!SCIPisInfinity(scip, lb));
7553  if( SCIPisInfinity(scip, -lb) )
7554  maxleftactivity = SCIPinfinity(scip);
7555  else
7556  maxleftactivity += val * lb;
7557  }
7558  }
7559  }
7560  ++i;
7561  }
7562 
7563  SCIPdebugMessage("minleftactivity = %.15g, rhs = %.15g\n",
7564  minleftactivity, consdata->rhs);
7565  SCIPdebugMessage("maxleftactivity = %.15g, lhs = %.15g\n",
7566  maxleftactivity, consdata->lhs);
7567 
7568  /* minleft == \infty ==> minactivity == \infty */
7569  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
7570  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
7571 
7572  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
7573  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
7574  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
7575  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
7576  */
7577  assert(!SCIPisInfinity(scip, minactivity));
7578  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
7579  return SCIP_OKAY;
7580 
7581  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
7582  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
7583  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
7584  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
7585  */
7586  assert(!SCIPisInfinity(scip, -maxactivity));
7587  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
7588  return SCIP_OKAY;
7589 
7590  /* correct lhs and rhs by min/max activity of surely non-redundant variables
7591  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
7592  */
7593  aggrlhs = consdata->lhs - minactivity + minleftactivity;
7594  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
7595 
7596  /* check if the constraint contains variables which are redundant. The reasoning is the following:
7597  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
7598  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
7599  * they can be removed from the constraint.
7600  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
7601  */
7602  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
7603  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
7604  {
7605  SCIP_Real minleftactivitypart;
7606  SCIP_Real maxleftactivitypart;
7607 
7608  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
7609 
7610  /* try to remove redundant variables from constraint */
7611  i = 0;
7612  while( i < consdata->nvars )
7613  {
7614  var = consdata->vars[i];
7615  minleftactivitypart = 0.0;
7616  maxleftactivitypart = 0.0;
7617  lb = SCIPvarGetLbLocal(var);
7618  ub = SCIPvarGetUbLocal(var);
7619 
7620  /* get coefficient and variable's bounds */
7621  val = consdata->vals[i];
7622  assert(!SCIPisZero(scip, val));
7623 
7624  /* check sign of coefficient */
7625  if( val >= 0.0 )
7626  {
7627  /* negation of condition above in case of positive val */
7628  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
7629  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
7630  {
7631  SCIPdebugMessage("minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
7632  SCIPdebugMessage("maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
7633  SCIPdebugMessage("linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
7634  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
7635 
7636  minleftactivitypart = val * lb;
7637  maxleftactivitypart = val * ub;
7638 
7639  SCIP_CALL( delCoefPos(scip, cons, i) );
7640  i--;
7641 
7642  /* get the new minimal and maximal activity of the constraint */
7643  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7644 
7645  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
7646  * huge contributions
7647  */
7648  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
7649  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
7650  }
7651  }
7652  else
7653  {
7654  /* negation of condition above in case of negative val */
7655  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
7656  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
7657  {
7658  SCIPdebugMessage("linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
7659  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
7660 
7661  minleftactivitypart = val * ub;
7662  maxleftactivitypart = val * lb;
7663 
7664  SCIP_CALL( delCoefPos(scip, cons, i) );
7665  i--;
7666 
7667  /* get the new minimal and maximal activity of the constraint */
7668  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7669 
7670  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
7671  * huge contributions
7672  */
7673  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
7674  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
7675  }
7676  }
7677 
7678  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
7679  * redundant variables could get deleted,
7680  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
7681  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
7682  * we would also delete y2 and as a result we would have gotten infeasibility */
7683  /* adjust lhs and right hand side */
7684  newlhs = consdata->lhs - minleftactivitypart;
7685  newrhs = consdata->rhs - maxleftactivitypart;
7686 
7687  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
7688  {
7689  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7690  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7691  ++(*nchgsides);
7692  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7693  }
7694  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
7695  {
7696  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7697  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7698  ++(*nchgsides);
7699  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7700  }
7701  ++i;
7702  }
7703  }
7704 
7705  return SCIP_OKAY;
7706 }
7707 
7708 /* processes equality with only one variable by fixing the variable and deleting the constraint */
7709 static
7711  SCIP* scip, /**< SCIP data structure */
7712  SCIP_CONS* cons, /**< linear constraint */
7713  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7714  int* nfixedvars, /**< pointer to count number of fixed variables */
7715  int* ndelconss /**< pointer to count number of deleted constraints */
7716  )
7717 {
7718  SCIP_CONSDATA* consdata;
7719  SCIP_VAR* var;
7720  SCIP_Real val;
7721  SCIP_Real fixval;
7722  SCIP_Bool infeasible;
7723  SCIP_Bool fixed;
7725  assert(scip != NULL);
7726  assert(cons != NULL);
7727  assert(cutoff != NULL);
7728  assert(nfixedvars != NULL);
7729  assert(ndelconss != NULL);
7730 
7731  consdata = SCIPconsGetData(cons);
7732  assert(consdata != NULL);
7733  assert(consdata->nvars == 1);
7734  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7735 
7736  /* calculate the value to fix the variable to */
7737  var = consdata->vars[0];
7738  val = consdata->vals[0];
7739  assert(!SCIPisZero(scip, val));
7740  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
7741  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
7742  SCIPdebugMessage("linear equality <%s>: fix <%s> == %.15g\n",
7743  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
7744 
7745  /* fix variable */
7746  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7747  if( infeasible )
7748  {
7749  SCIPdebugMessage(" -> infeasible fixing\n");
7750  *cutoff = TRUE;
7751  return SCIP_OKAY;
7752  }
7753  if( fixed )
7754  (*nfixedvars)++;
7755 
7756  /* disable constraint */
7757  SCIP_CALL( SCIPdelCons(scip, cons) );
7758  if( !consdata->upgraded )
7759  (*ndelconss)++;
7760 
7761  return SCIP_OKAY;
7762 }
7763 
7764 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
7765 static
7767  SCIP* scip, /**< SCIP data structure */
7768  SCIP_CONS* cons, /**< linear constraint */
7769  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7770  int* naggrvars, /**< pointer to count number of aggregated variables */
7771  int* ndelconss /**< pointer to count number of deleted constraints */
7772  )
7773 {
7774  SCIP_CONSDATA* consdata;
7775  SCIP_Bool infeasible;
7776  SCIP_Bool redundant;
7777  SCIP_Bool aggregated;
7778 
7779  assert(scip != NULL);
7780  assert(cons != NULL);
7781  assert(cutoff != NULL);
7782  assert(naggrvars != NULL);
7783  assert(ndelconss != NULL);
7784 
7785  consdata = SCIPconsGetData(cons);
7786  assert(consdata != NULL);
7787  assert(consdata->nvars == 2);
7788  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7789 
7790  SCIPdebugMessage("linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
7791  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
7792  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
7793 
7794  /* aggregate the equality */
7795  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
7796  consdata->rhs, &infeasible, &redundant, &aggregated) );
7797 
7798  /* check for infeasibility of aggregation */
7799  if( infeasible )
7800  {
7801  SCIPdebugMessage(" -> infeasible aggregation\n");
7802  *cutoff = TRUE;
7803  return SCIP_OKAY;
7804  }
7805 
7806  /* count the aggregation */
7807  if( aggregated )
7808  (*naggrvars)++;
7809 
7810  /* delete the constraint, if it is redundant */
7811  if( redundant )
7812  {
7813  SCIP_CALL( SCIPdelCons(scip, cons) );
7814 
7815  if( !consdata->upgraded )
7816  (*ndelconss)++;
7817  }
7818 
7819  return SCIP_OKAY;
7820 }
7821 
7822 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
7823 static
7825  SCIP* scip, /**< SCIP data structure */
7826  SCIP_CONSDATA* consdata, /**< linear constraint data */
7827  SCIP_VAR* slackvar, /**< variable to be aggregated out */
7828  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
7829  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
7830  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
7831  )
7832 {
7833  SCIP_Real slackvarlb;
7834  SCIP_Real slackvarub;
7835 
7836  assert(scip != NULL);
7837  assert(consdata != NULL);
7838  assert(newlhs != NULL);
7839  assert(newrhs != NULL);
7840  assert(!SCIPisInfinity(scip, -consdata->lhs));
7841  assert(!SCIPisInfinity(scip, consdata->rhs));
7842 
7843  slackvarlb = SCIPvarGetLbGlobal(slackvar);
7844  slackvarub = SCIPvarGetUbGlobal(slackvar);
7845  if( slackcoef > 0.0 )
7846  {
7847  if( SCIPisInfinity(scip, -slackvarlb) )
7848  *newrhs = SCIPinfinity(scip);
7849  else
7850  *newrhs = consdata->rhs - slackcoef * slackvarlb;
7851  if( SCIPisInfinity(scip, slackvarub) )
7852  *newlhs = -SCIPinfinity(scip);
7853  else
7854  *newlhs = consdata->lhs - slackcoef * slackvarub;
7855  }
7856  else
7857  {
7858  if( SCIPisInfinity(scip, -slackvarlb) )
7859  *newlhs = -SCIPinfinity(scip);
7860  else
7861  *newlhs = consdata->rhs - slackcoef * slackvarlb;
7862  if( SCIPisInfinity(scip, slackvarub) )
7863  *newrhs = SCIPinfinity(scip);
7864  else
7865  *newrhs = consdata->lhs - slackcoef * slackvarub;
7866  }
7867  assert(SCIPisLE(scip, *newlhs, *newrhs));
7868 }
7869 
7870 #define MAXMULTIAGGRQUOTIENT 1e+03
7871 
7872 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
7873  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
7874  * is implicitly integral by this constraint
7875  *
7876  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
7877  * can help.
7878  */
7879 static
7881  SCIP* scip, /**< SCIP data structure */
7882  SCIP_CONS* cons, /**< linear constraint */
7883  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7884  int* naggrvars, /**< pointer to count number of aggregated variables */
7885  int* ndelconss /**< pointer to count number of deleted constraints */
7886  )
7887 {
7888  SCIP_CONSDATA* consdata;
7889  SCIP_VAR** vars;
7890  SCIP_Real* vals;
7891  SCIP_VARTYPE bestslacktype;
7892  SCIP_VARTYPE slacktype;
7893  SCIP_Real lhs;
7895  SCIP_Real bestslackdomrng;
7896  SCIP_Real minabsval;
7897  SCIP_Real maxabsval;
7898  SCIP_Bool bestremovescons;
7899  SCIP_Bool coefszeroone;
7900  SCIP_Bool coefsintegral;
7901  SCIP_Bool varsintegral;
7902  SCIP_Bool infeasible;
7903  SCIP_Bool samevar;
7904  int supinf; /* counter for infinite contributions to the supremum of a possible
7905  * multi-aggregation
7906  */
7907  int infinf; /* counter for infinite contributions to the infimum of a possible
7908  * multi-aggregation
7909  */
7910  int maxnlocksstay;
7911  int maxnlocksremove;
7912  int bestslackpos;
7913  int bestnlocks;
7914  int ncontvars;
7915  int contvarpos;
7916  int nintvars;
7917  int nimplvars;
7918  int intvarpos;
7919  int v;
7920 
7921  assert(scip != NULL);
7922  assert(cons != NULL);
7923  assert(cutoff != NULL);
7924  assert(naggrvars != NULL);
7925 
7926  consdata = SCIPconsGetData(cons);
7927  assert(consdata != NULL);
7928  assert(consdata->nvars > 2);
7929  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7930 
7931  SCIPdebugMessage("linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
7932 
7933  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
7934  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
7935  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
7936  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
7937  */
7938  lhs = consdata->lhs;
7939  rhs = consdata->rhs;
7940  maxnlocksstay = 0;
7941  if( consdata->nvars == 3 )
7942  {
7943  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
7944  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
7945  */
7946  maxnlocksremove = 3;
7947  }
7948  else if( consdata->nvars == 4 )
7949  {
7950  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
7951  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
7952  */
7953  maxnlocksremove = 2;
7954  }
7955  else
7956  {
7957  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
7958  maxnlocksremove = 1;
7959  }
7960 
7961  /* the locks on this constraint can be ignored */
7962  if( SCIPconsIsChecked(cons) )
7963  {
7964  if( !SCIPisInfinity(scip, -lhs) )
7965  {
7966  maxnlocksstay++;
7967  maxnlocksremove++;
7968  }
7969  if( !SCIPisInfinity(scip, rhs) )
7970  {
7971  maxnlocksstay++;
7972  maxnlocksremove++;
7973  }
7974  }
7975 
7976  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
7977  vars = consdata->vars;
7978  vals = consdata->vals;
7979  bestslackpos = -1;
7980  bestslacktype = SCIP_VARTYPE_BINARY;
7981  bestnlocks = INT_MAX;
7982  bestremovescons = FALSE;
7983  bestslackdomrng = 0.0;
7984  coefszeroone = TRUE;
7985  coefsintegral = TRUE;
7986  varsintegral = TRUE;
7987  ncontvars = 0;
7988  contvarpos = -1;
7989  nintvars = 0;
7990  nimplvars = 0;
7991  intvarpos = -1;
7992  minabsval = SCIPinfinity(scip);
7993  maxabsval = -1.0;
7994  for( v = 0; v < consdata->nvars; ++v )
7995  {
7996  SCIP_VAR* var;
7997  SCIP_Real val;
7998  SCIP_Real absval;
7999  SCIP_Real varlb;
8000  SCIP_Real varub;
8001  SCIP_Bool iscont;
8002  int nlocks;
8003 
8004  assert(vars != NULL);
8005  assert(vals != NULL);
8006 
8007  var = vars[v];
8008  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDown(var) >= 1); /* because variable is locked in this equality */
8009  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUp(var) >= 1);
8010  varlb = SCIPvarGetLbGlobal(var);
8011  varub = SCIPvarGetUbGlobal(var);
8012 
8013  val = vals[v];
8014  absval = REALABS(val);
8015  assert(SCIPisPositive(scip, absval));
8016 
8017  /* calculate minimal and maximal absolute value */
8018  if( absval < minabsval )
8019  minabsval = absval;
8020  if( absval > maxabsval )
8021  maxabsval = absval;
8022 
8023  /* do not try to multi aggregate, when numerical bad */
8024  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
8025  return SCIP_OKAY;
8026 
8027  slacktype = SCIPvarGetType(var);
8028  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
8029  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
8030  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
8031  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
8032 
8033  /* update candidates for continuous -> implint and integer -> implint conversion */
8034  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
8035  {
8036  ncontvars++;
8037  contvarpos = v;
8038  }
8039  else if( slacktype == SCIP_VARTYPE_IMPLINT )
8040  {
8041  ++nimplvars;
8042  }
8043  else if( slacktype == SCIP_VARTYPE_INTEGER )
8044  {
8045  nintvars++;
8046  intvarpos = v;
8047  }
8048 
8049  /* check, if variable is already fixed or aggregated */
8050  if( !SCIPvarIsActive(var) )
8051  continue;
8052 
8053  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
8054  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
8055 
8056  if( nlocks > maxnlocksremove )
8057  continue;
8058 
8059  /* check, if variable can be used as a slack variable */
8060  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
8061  !SCIPdoNotMultaggrVar(scip, var) )
8062  {
8063  SCIP_Bool better;
8064  SCIP_Bool equal;
8065  SCIP_Real slackdomrng;
8066 
8067  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
8068  slackdomrng = SCIPinfinity(scip);
8069  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
8070  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
8071  return SCIP_OKAY;
8072  else
8073  {
8074  slackdomrng = (varub - varlb)*absval;
8075  assert(!SCIPisInfinity(scip, slackdomrng));
8076  }
8077  equal = FALSE;
8078  better = (slacktype > bestslacktype) || (bestslackpos == -1);
8079  if( !better && slacktype == bestslacktype )
8080  {
8081  better = (nlocks < bestnlocks);
8082  if( nlocks == bestnlocks && !bestremovescons )
8083  {
8084  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
8085  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
8086  }
8087  }
8088 
8089  if( better || equal )
8090  {
8091  SCIP_Real minresactivity;
8092  SCIP_Real maxresactivity;
8093  SCIP_Real newlhs;
8094  SCIP_Real newrhs;
8095  SCIP_Bool removescons;
8096  SCIP_Bool minisrelax;
8097  SCIP_Bool maxisrelax;
8098  SCIP_Bool isminsettoinfinity;
8099  SCIP_Bool ismaxsettoinfinity;
8100 
8101  /* check if the constraint becomes redundant after multi-aggregation */
8102  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
8103  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
8104 
8105  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
8106  * activity
8107  */
8108  if( minisrelax || maxisrelax )
8109  continue;
8110 
8111  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
8112  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
8113 
8114  /* check resactivities for reliability */
8115  if( removescons )
8116  {
8117  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
8118  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
8119 
8120  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
8121  && SCIPisFeasLE(scip, newlhs, minresactivity))
8122  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
8123 
8124  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
8125  }
8126 
8127  /* prefer variables that make the constraints redundant */
8128  if( bestremovescons && !removescons )
8129  continue;
8130 
8131  /* if the constraint does not become redundant, only accept the variable if it does not appear in
8132  * other constraints
8133  */
8134  if( !removescons && nlocks > maxnlocksstay )
8135  continue;
8136 
8137  better = better || (!bestremovescons && removescons);
8138  if( better )
8139  {
8140  bestslackpos = v;
8141  bestslacktype = slacktype;
8142  bestnlocks = nlocks;
8143  bestslackdomrng = slackdomrng;
8144  bestremovescons = removescons;
8145  }
8146  }
8147  }
8148  }
8149 
8150  /* if all coefficients and variables are integral, the right hand side must also be integral */
8151  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
8152  {
8153  SCIPdebugMessage("linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
8154  SCIPdebugPrintCons(scip, cons, NULL);
8155  *cutoff = TRUE;
8156  return SCIP_OKAY;
8157  }
8158 
8159  supinf = 0;
8160  infinf = 0;
8161  samevar = FALSE;
8162 
8163  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
8164  for( v = 0; v < consdata->nvars; ++v )
8165  {
8166  if( v != bestslackpos )
8167  {
8168  if( SCIPisPositive(scip, consdata->vals[v]) )
8169  {
8170  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
8171  {
8172  ++supinf;
8173  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
8174  {
8175  ++infinf;
8176  samevar = TRUE;
8177  }
8178  }
8179  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
8180  ++infinf;
8181 
8182  }
8183  else if( SCIPisNegative(scip, consdata->vals[v]) )
8184  {
8185  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
8186  {
8187  ++supinf;
8188  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
8189  {
8190  ++infinf;
8191  samevar = TRUE;
8192  }
8193  }
8194  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
8195  ++infinf;
8196  }
8197  }
8198  }
8199  assert(!samevar || (supinf > 0 && infinf > 0));
8200 
8201  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
8202  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
8203  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
8204  {
8205  SCIPdebugMessage("do not perform multi-aggregation: infimum and supremum are both infinite\n");
8206  return SCIP_OKAY;
8207  }
8208 
8209  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
8210  * we cannot aggregate the variable, because the integrality condition would get lost
8211  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
8212  * loose the integrality condition for this variable.
8213  */
8214  if( bestslackpos >= 0
8215  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
8216  || (coefsintegral && varsintegral && nimplvars == 0)) )
8217  {
8218  SCIP_VAR* slackvar;
8219  SCIP_Real* scalars;
8220  SCIP_Real slackcoef;
8221  SCIP_Real aggrconst;
8222  SCIP_Real newlhs;
8223  SCIP_Real newrhs;
8224  SCIP_Bool aggregated;
8225 
8226  /* we found a slack variable that only occurs in at most one other constraint:
8227  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
8228  */
8229  assert(bestslackpos < consdata->nvars);
8230 
8231  /* do not multi aggregate binary variables */
8232  if( SCIPvarIsBinary(vars[bestslackpos]) )
8233  return SCIP_OKAY;
8234 
8235  /* convert equality into inequality by deleting the slack variable:
8236  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
8237  */
8238  slackvar = vars[bestslackpos];
8239  slackcoef = vals[bestslackpos];
8240  assert(!SCIPisZero(scip, slackcoef));
8241  aggrconst = consdata->rhs/slackcoef;
8242 
8243  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
8244  assert(SCIPisLE(scip, newlhs, newrhs));
8245  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8246  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8247  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
8248 
8249  /* allocate temporary memory */
8250  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
8251 
8252  /* set up the multi-aggregation */
8253  SCIPdebugMessage("linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
8254  for( v = 0; v < consdata->nvars; ++v )
8255  {
8256  scalars[v] = -consdata->vals[v]/slackcoef;
8257  SCIPdebugPrintf(" %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
8258  }
8259  SCIPdebugPrintf(" %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
8260  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
8261  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
8262 
8263  /* perform the multi-aggregation */
8264  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
8265  &infeasible, &aggregated) );
8266  assert(aggregated);
8267 
8268  /* free temporary memory */
8269  SCIPfreeBufferArray(scip, &scalars);
8270 
8271  /* check for infeasible aggregation */
8272  if( infeasible )
8273  {
8274  SCIPdebugMessage("linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
8275  *cutoff = TRUE;
8276  return SCIP_OKAY;
8277  }
8278 
8279  (*naggrvars)++;
8280 
8281  /* delete the constraint if it became redundant */
8282  if( bestremovescons )
8283  {
8284  SCIPdebugMessage("linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
8285  SCIP_CALL( SCIPdelCons(scip, cons) );
8286 
8287  if( !consdata->upgraded )
8288  (*ndelconss)++;
8289  }
8290  }
8291  else if( ncontvars == 1 )
8292  {
8293  SCIP_VAR* var;
8294 
8295  assert(0 <= contvarpos && contvarpos < consdata->nvars);
8296  var = vars[contvarpos];
8297  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
8298 
8299  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
8300  {
8301  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
8302  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
8303  {
8304  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
8305  SCIPdebugMessage("linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
8306  SCIPconsGetName(cons), SCIPvarGetName(var));
8307  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
8308  if( infeasible )
8309  {
8310  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
8311  *cutoff = TRUE;
8312 
8313  return SCIP_OKAY;
8314  }
8315  }
8316  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
8317  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
8318  else if( !SCIPdoNotAggr(scip) )
8319  {
8320  SCIP_VAR* newvar;
8321  SCIP_Real absval;
8322  char newvarname[SCIP_MAXSTRLEN];
8323  SCIP_Bool redundant;
8324  SCIP_Bool aggregated;
8325 
8326  absval = REALABS(vals[contvarpos]);
8327 
8328  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
8329 
8330  /* create new implicit variable for aggregation */
8331  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
8333 
8334  /* add new variable to problem */
8335  SCIP_CALL( SCIPaddVar(scip, newvar) );
8336 
8337 #ifdef SCIP_DEBUG_SOLUTION
8338  if( SCIPdebugIsMainscip(scip) )
8339  {
8340  SCIP_Real varval;
8341  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
8342  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
8343  }
8344 #endif
8345 
8346  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
8347  SCIPdebugMessage("linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
8348  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
8349 
8350  /* aggregate continuous and implicit variable */
8351  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
8352 
8353  if( infeasible )
8354  {
8355  SCIPdebugMessage("infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
8356  SCIPvarGetName(var), SCIPvarGetName(newvar));
8357  *cutoff = TRUE;
8358 
8359  /* release implicit variable */
8360  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
8361 
8362  return SCIP_OKAY;
8363  }
8364 
8365  if( aggregated )
8366  (*naggrvars)++;
8367 
8368  /* release implicit variable */
8369  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
8370  }
8371 
8372  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
8373  * again
8374  */
8375  consdata->boundstightened = FALSE;
8376  consdata->presolved = FALSE;
8377  }
8378  }
8379  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
8380  {
8381  SCIP_VAR* var;
8382 
8383  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
8384  * -> we don't convert integers into implints if the row is a 0/1-row
8385  */
8386  assert(varsintegral);
8387  assert(0 <= intvarpos && intvarpos < consdata->nvars);
8388  var = vars[intvarpos];
8389  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
8390 
8391  if( coefsintegral
8392  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
8393  && SCIPisFeasIntegral(scip, consdata->rhs) )
8394  {
8395  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
8396  SCIPdebugMessage("linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
8397  SCIPconsGetName(cons), SCIPvarGetName(var));
8398  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
8399  if( infeasible )
8400  {
8401  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
8402  *cutoff = TRUE;
8403 
8404  return SCIP_OKAY;
8405  }
8406  }
8407  }
8408 
8409  return SCIP_OKAY;
8410 }
8411 
8412 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
8413 static
8415  SCIP* scip, /**< SCIP data structure */
8416  SCIP_CONSDATA* consdata, /**< linear constraint data */
8417  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
8418  * objective function
8419  */
8420  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
8421  * this constraint
8422  */
8423  )
8424 {
8425  SCIP_VAR** vars;
8426  SCIP_VAR* var;
8427  SCIP_Real objval;
8428  SCIP_Bool negated;
8429  int nvars;
8430  int v;
8431 
8432  vars = consdata->vars;
8433  nvars = consdata->nvars;
8434  assert(vars != NULL);
8435 
8436  for( v = 0; v < nvars; ++v )
8437  {
8438  negated = FALSE;
8439  var = vars[v];
8440  assert(vars != NULL);
8441 
8442  if( SCIPvarIsNegated(var) )
8443  {
8444  negated = TRUE;
8445  var = SCIPvarGetNegatedVar(var);
8446  assert(var != NULL);
8447  }
8448 
8449  objval = SCIPvarGetObj(var);
8450 
8451  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
8452  * function
8453  */
8454  if( SCIPisZero(scip, objval) )
8455  return FALSE;
8456  else
8457  {
8458  SCIP_Real val;
8459 
8460  val = consdata->vals[v];
8461 
8462  if( negated )
8463  {
8464  if( v == 0 )
8465  {
8466  /* the first variable defines the scale */
8467  (*scale) = val / -objval;
8468 
8469  (*offset) += val;
8470  }
8471  else if( SCIPisEQ(scip, -objval * (*scale), val) )
8472  (*offset) += val;
8473  else
8474  return FALSE;
8475  }
8476  else if( v == 0 )
8477  {
8478  /* the first variable defines the scale */
8479  (*scale) = val / objval;
8480  }
8481  else if( !SCIPisEQ(scip, objval * (*scale), val) )
8482  return FALSE;
8483  }
8484  }
8485 
8486  return TRUE;
8487 }
8488 
8489 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
8490  * objective coefficients and add an objective offset
8491  */
8492 static
8494  SCIP* scip, /**< SCIP data structure */
8495  SCIP_CONS* cons, /**< linear equation constraint */
8496  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
8497  )
8498 {
8499  SCIP_CONSDATA* consdata;
8500  SCIP_Real offset;
8501  SCIP_Real scale;
8502  SCIP_Bool applicable;
8503  int nobjvars;
8504  int nvars;
8505  int v;
8506 
8507  assert(scip != NULL);
8508  assert(cons != NULL);
8509  assert(conshdlrdata != NULL);
8510 
8511  consdata = SCIPconsGetData(cons);
8512  assert(consdata != NULL);
8513  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
8514 
8515  nvars = consdata->nvars;
8516  nobjvars = SCIPgetNObjVars(scip);
8517 
8518  /* check if the linear equality constraints does not have more variables than the objective function */
8519  if( nvars > nobjvars || nvars == 0 )
8520  return SCIP_OKAY;
8521 
8522  /* check for allowance of algorithm */
8523  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
8524  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
8525  return SCIP_OKAY;
8526 
8527  offset = consdata->rhs;
8528  scale = 1.0;
8529 
8530  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
8531  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
8532 
8533  if( applicable )
8534  {
8535  SCIP_VAR** vars;
8536 
8537  vars = consdata->vars;
8538  assert(vars != NULL);
8539 
8540  offset /= scale;
8541 
8542  SCIPdebugMessage("linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
8543  SCIPconsGetName(cons), consdata->rhs, offset);
8544 
8545  /* set all objective coefficient to zero */
8546  for( v = 0; v < nvars; ++v )
8547  {
8548  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
8549  }
8550 
8551  /* add an objective offset */
8552  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
8553  }
8554 
8555  return SCIP_OKAY;
8556 }
8557 
8558 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
8559 static
8561  SCIP* scip, /**< SCIP data structure */
8562  SCIP_CONS* cons, /**< constraint */
8563  SCIP_Real primalbound /**< feasible primal bound */
8564  )
8565 {
8566  SCIP_Real cutoffbound;
8567 
8568  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
8569  * accepted
8570  */
8571  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
8572 
8573  if( cutoffbound < SCIPgetCutoffbound(scip) )
8574  {
8575  SCIPdebugMessage("update cutoff bound <%g>\n", cutoffbound);
8576 
8577  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
8578  }
8579  else
8580  {
8581  SCIP_CONSDATA* consdata;
8582 
8583  consdata = SCIPconsGetData(cons);
8584  assert(consdata != NULL);
8585 
8586  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
8587  * resulted from one side
8588  */
8589  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
8590  {
8591  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
8592  * propagation
8593  */
8594  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
8595  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
8596  }
8597  }
8598 
8599  return SCIP_OKAY;
8600 }
8601 
8602 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
8603  * constraint enters the LP by setting the initial and separated flag to FALSE
8604  */
8605 static
8607  SCIP* scip, /**< SCIP data structure */
8608  SCIP_CONS* cons, /**< linear constraint */
8609  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
8610  )
8611 {
8612  SCIP_CONSDATA* consdata;
8613  SCIP_Real offset;
8614  SCIP_Real scale;
8615  SCIP_Bool applicable;
8616  int nobjvars;
8617  int nvars;
8618 
8619  assert(scip != NULL);
8620  assert(cons != NULL);
8621  assert(conshdlrdata != NULL);
8622 
8623  consdata = SCIPconsGetData(cons);
8624  assert(consdata != NULL);
8625 
8626  /* ignore equalities since these are covert by the method checkPartialObjective() */
8627  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
8628  return SCIP_OKAY;
8629 
8630  nvars = consdata->nvars;
8631  nobjvars = SCIPgetNObjVars(scip);
8632 
8633  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
8634  * initial and/or separated flag is set to FALSE
8635  */
8636  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
8637  return SCIP_OKAY;
8638 
8639  offset = 0.0;
8640  scale = 1.0;
8641 
8642  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
8643  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
8644 
8645  if( applicable )
8646  {
8647  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
8648  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
8649 
8650  if( SCIPisPositive(scip, scale) )
8651  {
8652  if( conshdlrdata->detectcutoffbound && rhsfinite )
8653  {
8654  SCIP_Real primalbound;
8655 
8656  primalbound = (consdata->rhs - offset) / scale;
8657 
8658  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
8659  SCIPconsGetName(cons), primalbound);
8660 
8661  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
8662  }
8663 
8664  if( conshdlrdata->detectlowerbound && lhsfinite )
8665  {
8666  SCIP_Real lowerbound;
8667 
8668  lowerbound = (consdata->lhs - offset) / scale;
8669 
8670  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
8671  SCIPconsGetName(cons), lowerbound);
8672 
8673  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
8674  }
8675 
8676  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
8677  (conshdlrdata->detectlowerbound && !rhsfinite) )
8678  {
8679  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
8680  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
8681  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
8682  }
8683  }
8684  else
8685  {
8686  if( conshdlrdata->detectlowerbound && rhsfinite )
8687  {
8688  SCIP_Real lowerbound;
8689 
8690  lowerbound = (consdata->rhs - offset) / scale;
8691 
8692  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
8693  SCIPconsGetName(cons), lowerbound);
8694 
8695  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
8696  }
8697 
8698  if( conshdlrdata->detectcutoffbound && lhsfinite )
8699  {
8700  SCIP_Real primalbound;
8701 
8702  primalbound = (consdata->lhs - offset) / scale;
8703 
8704  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
8705  SCIPconsGetName(cons), primalbound);
8706 
8707  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
8708  }
8709 
8710  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
8711  (conshdlrdata->detectlowerbound && !lhsfinite) )
8712  {
8713  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
8714  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
8715  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
8716  }
8717  }
8718  }
8719 
8720  return SCIP_OKAY;
8721 }
8722 
8723 /** converts special equalities */
8724 static
8726  SCIP* scip, /**< SCIP data structure */
8727  SCIP_CONS* cons, /**< linear constraint */
8728  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
8729  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
8730  int* nfixedvars, /**< pointer to count number of fixed variables */
8731  int* naggrvars, /**< pointer to count number of aggregated variables */
8732  int* ndelconss /**< pointer to count number of deleted constraints */
8733  )
8734 {
8735  SCIP_CONSDATA* consdata;
8736 
8737  assert(scip != NULL);
8738  assert(cons != NULL);
8739  assert(conshdlrdata != NULL);
8740  assert(cutoff != NULL);
8741  assert(nfixedvars != NULL);
8742  assert(naggrvars != NULL);
8743  assert(ndelconss != NULL);
8744 
8745  consdata = SCIPconsGetData(cons);
8746  assert(consdata != NULL);
8747  assert(consdata->removedfixings);
8748 
8749  /* do nothing on inequalities */
8750  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
8751  return SCIP_OKAY;
8752 
8753  /* depending on the number of variables, call a special conversion method */
8754  if( consdata->nvars == 1 )
8755  {
8756  /* fix variable */
8757  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
8758  }
8759  else if( consdata->nvars == 2 )
8760  {
8761  /* aggregate one of the variables */
8762  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
8763  }
8764  else
8765  {
8766  /* check if the equality is part of the objective function */
8767  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
8768 
8769  /* try to multi-aggregate one of the variables */
8770  SCIP_CALL( convertLongEquality(scip, cons, cutoff, naggrvars, ndelconss) );
8771  }
8772 
8773  return SCIP_OKAY;
8774 }
8775 
8776 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
8777  * integral
8778  */
8779 static
8781  SCIP* scip, /**< SCIP data structure */
8782  SCIP_CONSDATA* consdata, /**< linear constraint */
8783  int pos, /**< position of variable to be left out */
8784  SCIP_Real val /**< value to divide the coefficients by */
8785  )
8786 {
8787  int v;
8788 
8789  assert(scip != NULL);
8790  assert(consdata != NULL);
8791  assert(0 <= pos && pos < consdata->nvars);
8792 
8793  for( v = 0; v < consdata->nvars; ++v )
8794  {
8795  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
8796  return FALSE;
8797  }
8798 
8799  return TRUE;
8800 }
8801 
8802 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
8803  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
8804  */
8805 static
8807  SCIP* scip, /**< SCIP data structure */
8808  SCIP_Real side, /**< lhs or rhs */
8809  SCIP_Real val, /**< coefficient */
8810  SCIP_Real minresactivity, /**< minimal residual activity */
8811  SCIP_Real maxresactivity, /**< maximal residual activity */
8812  SCIP_Real* minval, /**< pointer to store calculated minval */
8813  SCIP_Real* maxval /**< pointer to store calculated maxval */
8814  )
8815 {
8816  assert(scip != NULL);
8817  assert(minval != NULL);
8818  assert(maxval != NULL);
8819 
8820  if( val > 0.0 )
8821  {
8822  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
8823  *minval = -maxresactivity;
8824  else
8825  *minval = (side - maxresactivity)/val;
8826 
8827  if( SCIPisInfinity(scip, ABS(minresactivity)) )
8828  *maxval = -minresactivity;
8829  else
8830  *maxval = (side - minresactivity)/val;
8831  }
8832  else
8833  {
8834  if( SCIPisInfinity(scip, ABS(minresactivity)) )
8835  *minval = minresactivity;
8836  else
8837  *minval = (side - minresactivity)/val;
8838 
8839  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
8840  *maxval = maxresactivity;
8841  else
8842  *maxval = (side - maxresactivity)/val;
8843  }
8844 }
8845 
8846 
8847 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
8848  * linear inequality
8849  */
8850 static
8852  SCIP* scip, /**< SCIP data structure */
8853  SCIP_CONS* cons, /**< linear constraint */
8854  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
8855  int* nfixedvars, /**< pointer to count number of fixed variables */
8856  int* naggrvars, /**< pointer to count number of aggregated variables */
8857  int* ndelconss /**< pointer to count number of deleted constraints */
8858  )
8859 {
8860  SCIP_CONSDATA* consdata;
8861  SCIP_Bool lhsexists;
8862  SCIP_Bool rhsexists;
8863  SCIP_Bool bestisint;
8864  SCIP_Bool bestislhs;
8865  int bestpos;
8866  int i;
8867  int maxotherlocks;
8868 
8869  assert(scip != NULL);
8870  assert(cons != NULL);
8871  assert(cutoff != NULL);
8872  assert(nfixedvars != NULL);
8873  assert(naggrvars != NULL);
8874  assert(ndelconss != NULL);
8875 
8876  /* only process checked constraints (for which the locks are increased);
8877  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
8878  * dualfix presolver
8879  */
8880  if( !SCIPconsIsChecked(cons) )
8881  return SCIP_OKAY;
8882 
8883  consdata = SCIPconsGetData(cons);
8884  assert(consdata != NULL);
8885 
8886  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
8887  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
8888 
8889  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
8890  * can use it safely for aggregation and break the search loop
8891  */
8892  bestpos = -1;
8893  bestisint = TRUE;
8894  bestislhs = FALSE;
8895 
8896  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
8897  * everything else would produce fill-in. Exceptions:
8898  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
8899  * produced.
8900  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
8901  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
8902  * six nonzeros (two variables per substitution).
8903  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
8904  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
8905  * six nonzeros (three variables per substitution). God exists!
8906  */
8907  if( consdata->nvars <= 2 )
8908  maxotherlocks = INT_MAX;
8909  else if( consdata->nvars == 3 )
8910  maxotherlocks = 3;
8911  else if( consdata->nvars == 4 )
8912  maxotherlocks = 2;
8913  else
8914  maxotherlocks = 1;
8915 
8916  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
8917  if( lhsexists && rhsexists )
8918  maxotherlocks++;
8919 
8920  for( i = 0; i < consdata->nvars && bestisint; ++i )
8921  {
8922  SCIP_VAR* var;
8923  SCIP_Bool isint;
8924  SCIP_Real val;
8925  SCIP_Real obj;
8926  SCIP_Real lb;
8927  SCIP_Real ub;
8928  SCIP_Bool agglhs;
8929  SCIP_Bool aggrhs;
8930 
8931  var = consdata->vars[i];
8933 
8934  /* if we already found a candidate, skip integers */
8935  if( bestpos >= 0 && isint )
8936  continue;
8937 
8938  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
8939  * active, fixed, or single-aggregated with another binary variable
8940  */
8941  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
8942  continue;
8943 
8944  if ( SCIPdoNotMultaggrVar(scip, var) )
8945  continue;
8946 
8947  val = consdata->vals[i];
8948  obj = SCIPvarGetObj(var);
8949  lb = SCIPvarGetLbGlobal(var);
8950  ub = SCIPvarGetUbGlobal(var);
8951 
8952  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
8953  *
8954  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
8955  * - constraint is the only one that forbids fixing the variable to its lower bound
8956  * - 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
8957  *
8958  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
8959  * - constraint is the only one that forbids fixing the variable to its upper bound
8960  * - 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
8961  *
8962  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
8963  * - constraint is the only one that forbids fixing the variable to its upper bound
8964  * - 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
8965  *
8966  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
8967  * - constraint is the only one that forbids fixing the variable to its lower bound
8968  * - 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
8969  *
8970  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
8971  * of all x_j
8972  * furthermore: we only want to apply this, if no fill-in will be produced
8973  */
8974  agglhs = lhsexists
8975  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
8976  && SCIPvarGetNLocksUp(var) <= maxotherlocks)
8977  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
8978  && SCIPvarGetNLocksDown(var) <= maxotherlocks));
8979  aggrhs = rhsexists
8980  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
8981  && SCIPvarGetNLocksDown(var) <= maxotherlocks)
8982  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
8983  && SCIPvarGetNLocksUp(var) <= maxotherlocks));
8984  if( agglhs || aggrhs )
8985  {
8986  SCIP_Real minresactivity;
8987  SCIP_Real maxresactivity;
8988  SCIP_Real minval;
8989  SCIP_Real maxval;
8990  SCIP_Bool minisrelax;
8991  SCIP_Bool maxisrelax;
8992  SCIP_Bool isminsettoinfinity;
8993  SCIP_Bool ismaxsettoinfinity;
8994 
8995  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
8996  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
8997  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
8998  assert(SCIPisLE(scip, minresactivity, maxresactivity));
8999 
9000  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
9001  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
9002  * This is needed, because we do not want to rely on relaxed finite resactivities.
9003  */
9004  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
9005 
9006  if( agglhs )
9007  {
9008  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
9009  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
9010 
9011  assert(SCIPisLE(scip, minval, maxval));
9012  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
9013  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
9014  {
9015  SCIP_Real oldmaxresactivity;
9016  SCIP_Real oldminresactivity;
9017  SCIP_Bool recalculated;
9018 
9019  recalculated = FALSE;
9020  oldmaxresactivity = maxresactivity;
9021  oldminresactivity = minresactivity;
9022 
9023  /* check minresactivity for reliability */
9024  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9025  {
9026  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9027  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
9028  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
9029  }
9030 
9031  /* check maxresactivity for reliability */
9032  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
9033  {
9034  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9035  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
9036  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
9037  }
9038 
9039  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
9040  if( recalculated )
9041  {
9042  assert(SCIPisLE(scip, minresactivity, maxresactivity));
9043 
9044  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
9045  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
9046 
9047  assert(SCIPisLE(scip, minval, maxval));
9048  }
9049 
9050  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
9051  {
9052  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
9053  * in the multi-aggregation
9054  */
9055  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
9056  {
9057  bestpos = i;
9058  bestisint = isint;
9059  bestislhs = TRUE;
9060  continue; /* no need to also look at the right hand side */
9061  }
9062  }
9063  }
9064  }
9065 
9066  if( aggrhs )
9067  {
9068  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
9069  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
9070 
9071  assert(SCIPisLE(scip,minval,maxval));
9072  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
9073  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
9074  {
9075  SCIP_Real oldmaxresactivity;
9076  SCIP_Real oldminresactivity;
9077  SCIP_Bool recalculated;
9078 
9079  recalculated = FALSE;
9080  oldmaxresactivity = maxresactivity;
9081  oldminresactivity = minresactivity;
9082 
9083  /* check minresactivity for reliability */
9084  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9085  {
9086  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9087  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
9088  }
9089 
9090  /* check maxresactivity for reliability */
9091  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
9092  {
9093  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9094  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
9095  }
9096 
9097  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
9098  if( recalculated )
9099  {
9100  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
9101  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
9102  assert(SCIPisLE(scip,minval,maxval));
9103  }
9104 
9105  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
9106  {
9107  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
9108  * in the multi-aggregation
9109  */
9110  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
9111  {
9112  bestpos = i;
9113  bestisint = isint;
9114  bestislhs = FALSE;
9115  }
9116  }
9117  }
9118  }
9119  }
9120  }
9121 
9122  if( bestpos >= 0 )
9123  {
9124  SCIP_VAR** aggrvars;
9125  SCIP_Real* aggrcoefs;
9126  SCIP_Real aggrconst;
9127  SCIP_VAR* bestvar;
9128  SCIP_Real bestval;
9129  int naggrs;
9130  int j;
9131  SCIP_Bool infeasible;
9132  SCIP_Bool aggregated;
9133  SCIP_Bool samevar;
9134  int supinf; /* counter for infinite contributions to the supremum of a possible
9135  * multi-aggregation
9136  */
9137  int infinf; /* counter for infinite contributions to the infimum of a possible
9138  * multi-aggregation
9139  */
9140 
9141  assert(!bestislhs || lhsexists);
9142  assert(bestislhs || rhsexists);
9143 
9144  bestvar = consdata->vars[bestpos];
9145  bestval = consdata->vals[bestpos];
9146  assert(bestisint ==
9148 
9149  /* allocate temporary memory */
9150  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
9151  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
9152 
9153  /* set up the multi-aggregation */
9154  SCIPdebugPrintCons(scip, cons, NULL);
9155  SCIPdebugMessage("linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
9156  naggrs = 0;
9157  supinf = 0;
9158  infinf = 0;
9159  samevar = FALSE;
9160 
9161  for( j = 0; j < consdata->nvars; ++j )
9162  {
9163  if( j != bestpos )
9164  {
9165  aggrvars[naggrs] = consdata->vars[j];
9166  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
9167  SCIPdebugPrintf(" %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
9168  if( bestisint )
9169  {
9170  /* coefficient must be integral: round it to exact integral value */
9171  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
9172  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
9173  }
9174 
9175  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
9176  {
9177  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
9178  {
9179  ++supinf;
9180  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
9181  {
9182  ++infinf;
9183  samevar = TRUE;
9184  }
9185  }
9186  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
9187  ++infinf;
9188  }
9189  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
9190  {
9191  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
9192  {
9193  ++supinf;
9194  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
9195  {
9196  ++infinf;
9197  samevar = TRUE;
9198  }
9199  }
9200  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
9201  ++infinf;
9202  }
9203 
9204  naggrs++;
9205  }
9206  }
9207  assert(!samevar || (supinf > 0 && infinf > 0));
9208 
9209  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
9210  SCIPdebugPrintf(" %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
9211  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
9212  assert(naggrs == consdata->nvars-1);
9213 
9214  /* right hand side must be integral: round it to exact integral value */
9215  if( bestisint )
9216  {
9217  assert(SCIPisIntegral(scip, aggrconst));
9218  aggrconst = SCIPfloor(scip, aggrconst+0.5);
9219  }
9220 
9221  aggregated = FALSE;
9222  infeasible = FALSE;
9223 
9224  /* perform the multi-aggregation */
9225  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
9226  {
9227  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
9228  * also convertLongEquality() early termination due to coefficients
9229  */
9230  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
9231  }
9232  else
9233  {
9234  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9235  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9236  SCIPdebugMessage("do not perform multi-aggregation: infimum and supremum are both infinite\n");
9237  }
9238  /* free temporary memory */
9239  SCIPfreeBufferArray(scip, &aggrcoefs);
9240  SCIPfreeBufferArray(scip, &aggrvars);
9241 
9242  /* check for infeasible aggregation */
9243  if( infeasible )
9244  {
9245  SCIPdebugMessage("linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9246  *cutoff = TRUE;
9247  return SCIP_OKAY;
9248  }
9249 
9250  /* delete the constraint, if the aggregation was successful */
9251  if( aggregated )
9252  {
9253  SCIP_CALL( SCIPdelCons(scip, cons) );
9254 
9255  if( !consdata->upgraded )
9256  (*ndelconss)++;
9257  (*naggrvars)++;
9258  }
9259  else
9260  {
9261  SCIPdebugMessage("aggregation non successful!\n");
9262  }
9263  }
9264 
9265  return SCIP_OKAY;
9266 }
9267 
9268 #define BINWEIGHT 1
9269 #define INTWEIGHT 4
9270 #define CONTWEIGHT 8
9271 
9272 /** gets weight for variable in a "weighted number of variables" sum */
9273 static
9274 int getVarWeight(
9275  SCIP_VAR* var /**< variable to get weight for */
9276  )
9277 {
9278  switch( SCIPvarGetType(var) )
9279  {
9280  case SCIP_VARTYPE_BINARY:
9281  return BINWEIGHT;
9284  return INTWEIGHT;
9286  return CONTWEIGHT;
9287  default:
9288  SCIPerrorMessage("invalid variable type\n");
9289  SCIPABORT();
9290  return 0; /*lint !e527*/
9291  }
9292 }
9293 
9294 /** tries to aggregate variables in equations a^Tx = lhs
9295  * in case there are at most two binary variables with an odd coefficient and all other
9296  * variables are not continuous and have an even coefficient then:
9297  * - exactly one odd binary variables
9298  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
9299  * - lhs is odd -> y = 1
9300  * - lhs is even -> y = 0
9301  * - exactly two odd binary variables
9302  * aggregate the two binary variables with odd coefficient
9303  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
9304  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
9305  */
9306 static
9308  SCIP* scip, /**< SCIP data structure */
9309  SCIP_CONS* cons, /**< linear constraint */
9310  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9311  int* nfixedvars, /**< pointer to count number of fixed variables */
9312  int* naggrvars, /**< pointer to count number of aggregated variables */
9313  int* ndelconss /**< pointer to count number of deleted constraints */
9314  )
9315 { /*lint --e{715}*/
9316  SCIP_CONSDATA* consdata;
9317  SCIP_Bool success;
9318 
9319  assert( scip != NULL );
9320  assert( cons != NULL );
9322  consdata = SCIPconsGetData(cons);
9323  assert( consdata != NULL );
9324 
9325  /* check if the linear constraint is an equation with integral right hand side */
9326  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
9327  return SCIP_OKAY;
9328 
9329  /* try to fix and aggregated variables until nothing is possible anymore */
9330  do
9331  {
9332  int v;
9333  int nvars;
9334  SCIP_VAR** vars;
9335  SCIP_Real* vals;
9336  SCIP_Real lhs;
9337  SCIP_Bool lhsodd;
9338 
9339  SCIP_Bool infeasible;
9340  SCIP_Bool fixed;
9341  SCIP_Bool aggregated;
9342  SCIP_Bool redundant;
9343 
9344  SCIP_VAR* var1;
9345  SCIP_VAR* var2;
9346  int noddvars;
9347 
9348  success = FALSE;
9349 
9350  lhs = consdata->lhs;
9351  vars = consdata->vars;
9352  vals = consdata->vals;
9353  nvars = consdata->nvars;
9354 
9355  assert( !SCIPisInfinity(scip, ABS(lhs)) );
9356 
9357  var1 = NULL;
9358  var2 = NULL;
9359  noddvars = 0;
9360 
9361  /* search for binary variables with an odd coefficient */
9362  for( v = 0; v < nvars && noddvars < 3; ++v )
9363  {
9364  SCIP_Longint val;
9365 
9366  /* all coefficients and variables have to be integral */
9367  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9368  return SCIP_OKAY;
9369 
9370  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
9371  if( val % 2 != 0 )
9372  {
9373  /* the odd values have to belong to binary variables */
9374  if( !SCIPvarIsBinary(vars[v]) )
9375  return SCIP_OKAY;
9376 
9377  if( noddvars == 0 )
9378  var1 = vars[v];
9379  else
9380  var2 = vars[v];
9381 
9382  noddvars++;
9383  }
9384  }
9385 
9386  /* check lhs is odd or even */
9387  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
9388 
9389  if( noddvars == 1 )
9390  {
9391  assert( var1 != NULL );
9392 
9393  SCIPdebugMessage("linear constraint <%s>: try fixing variable <%s> to <%g>\n",
9394  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
9395 
9396  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
9397 
9398  /* check for infeasibility of fixing */
9399  if( infeasible )
9400  {
9401  SCIPdebugMessage(" -> infeasible fixing\n");
9402  *cutoff = TRUE;
9403  return SCIP_OKAY;
9404  }
9405 
9406  if( fixed )
9407  {
9408  SCIPdebugMessage(" -> feasible fixing\n");
9409  (*nfixedvars)++;
9410  success = TRUE;
9411  }
9412  }
9413  else if( noddvars == 2 )
9414  {
9415  assert( var1 != NULL );
9416  assert( var2 != NULL );
9417 
9418  /* aggregate the two variables with odd coefficient
9419  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
9420  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
9421  */
9422  SCIPdebugMessage("linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
9423  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
9424 
9425  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
9426  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
9427 
9428  /* check for infeasibility of aggregation */
9429  if( infeasible )
9430  {
9431  SCIPdebugMessage(" -> infeasible aggregation\n");
9432  *cutoff = TRUE;
9433  return SCIP_OKAY;
9434  }
9435 
9436  /* count the aggregation */
9437  if( aggregated )
9438  {
9439  SCIPdebugMessage(" -> feasible aggregation\n");
9440  (*naggrvars)++;
9441  success = TRUE;
9442  }
9443  }
9444 
9445  if( success )
9446  {
9447  /* apply fixings and aggregation to successfully rerun this presolving step */
9448  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
9449 
9450  if( infeasible )
9451  {
9452  SCIPdebugMessage(" -> infeasible fixing\n");
9453  *cutoff = TRUE;
9454  return SCIP_OKAY;
9455  }
9456 
9457  /* normalize constraint */
9458  SCIP_CALL( normalizeCons(scip, cons) );
9459  }
9460  }
9461  while( success );
9462 
9463  return SCIP_OKAY;
9464 }
9465 
9466 
9467 
9468 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
9469  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
9470  * coefficients
9471  */
9472 static
9473 SCIP_DECL_SORTINDCOMP(consdataCompSim)
9474 { /*lint --e{715}*/
9475  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
9476  SCIP_VARTYPE vartype1;
9477  SCIP_VARTYPE vartype2;
9478  SCIP_Real value;
9479 
9480  assert(consdata != NULL);
9481  assert(0 <= ind1 && ind1 < consdata->nvars);
9482  assert(0 <= ind2 && ind2 < consdata->nvars);
9483 
9484  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
9485  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
9486 
9487  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
9488  {
9489  /* continuous varibles will be sorted to the back */
9490  if( vartype2 != vartype1 )
9491  return +1;
9492  /* both variables are continuous */
9493  else
9494  return 0;
9495  }
9496  /* continuous variables will be sorted to the back */
9497  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
9498  return -1;
9499 
9500  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
9501 
9502  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
9503  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
9504 }
9505 
9506 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
9507  * common divisor
9508  *
9509  * 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
9510  * constraint to 1^Tx = 1
9511  */
9512 static
9514  SCIP* scip, /**< SCIP data structure */
9515  SCIP_CONS* cons, /**< linear constraint */
9516  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
9517  int* nchgsides /**< pointer to store the amount of changed sides */
9518  )
9519 {
9520  SCIP_CONSDATA* consdata;
9521  SCIP_VAR** vars;
9522  SCIP_Real* vals;
9523  SCIP_Real minval;
9524  SCIP_Real secondminval;
9525  SCIP_Real maxval;
9526  SCIP_Real lhs;
9528  int nvars;
9529  int v;
9530 
9531  /* we must not change a modifiable constraint in any way */
9532  if( SCIPconsIsModifiable(cons) )
9533  return SCIP_OKAY;
9534 
9535  if( SCIPconsIsDeleted(cons) )
9536  return SCIP_OKAY;
9537 
9538  consdata = SCIPconsGetData(cons);
9539  assert(consdata != NULL);
9540 
9541  nvars = consdata->nvars;
9542 
9543  /* do not check empty or bound-constraints */
9544  if( nvars < 2 )
9545  return SCIP_OKAY;
9546 
9547  vals = consdata->vals;
9548  vars = consdata->vars;
9549  assert(vars != NULL);
9550  assert(vals != NULL);
9551 
9552  lhs = consdata->lhs;
9553  rhs = consdata->rhs;
9554  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
9555  assert(!SCIPisNegative(scip, rhs));
9556 
9557  minval = SCIP_INVALID;
9558  secondminval = SCIP_INVALID;
9559  maxval = -SCIP_INVALID;
9560 
9561  for( v = nvars - 1; v >= 0; --v )
9562  {
9563  if( SCIPvarIsBinary(vars[v]) )
9564  {
9565  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
9566  {
9567  secondminval = minval;
9568  minval = vals[v];
9569  }
9570  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
9571  secondminval = vals[v];
9572 
9573  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
9574  maxval = vals[v];
9575  }
9576  else
9577  break;
9578  }
9579 
9580  /* check if all variables are binary */
9581  if( v == -1 )
9582  {
9583  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
9584  return SCIP_OKAY;
9585 
9586  /* check if we can and need to choose exactly one binary variable */
9587  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
9588  {
9589  /* change all coefficients to 1.0 */
9590  for( v = nvars - 1; v >= 0; --v )
9591  {
9592  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
9593  }
9594  (*nchgcoefs) += nvars;
9595 
9596  /* replace old right and left hand side with 1.0 */
9597  SCIP_CALL( chgRhs(scip, cons, 1.0) );
9598  SCIP_CALL( chgLhs(scip, cons, 1.0) );
9599  (*nchgsides) += 2;
9600  }
9601  }
9602 
9603  return SCIP_OKAY;
9604 }
9605 
9606 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
9607  * for equations @see rangedRowSimplify() will be called
9608  *
9609  * there are several different coefficient reduction steps which will be applied
9610  *
9611  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
9612  *
9613  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
9614  *
9615  * 2. We try to remove redundant fractional parts in a constraint
9616  *
9617  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
9618  *
9619  * 3. We are using the greatest common divisor for further reductions
9620  *
9621  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
9622  * integral
9623  */
9624 static
9626  SCIP* scip, /**< SCIP data structure */
9627  SCIP_CONS* cons, /**< linear constraint */
9628  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
9629  int* nchgsides /**< pointer to store the amount of changed sides */
9630  )
9631 {
9632  SCIP_CONSDATA* consdata;
9633  SCIP_VAR** vars;
9634  SCIP_Real* vals;
9635  int* perm;
9636  SCIP_Real minactsub;
9637  SCIP_Real maxactsub;
9638  SCIP_Real siderest;
9639  SCIP_Real feastol;
9640  SCIP_Real newcoef;
9641  SCIP_Real absval;
9642  SCIP_Real side;
9643  SCIP_Real lhs;
9644  SCIP_Real rhs;
9645  SCIP_Real lb;
9646  SCIP_Real ub;
9647  SCIP_Longint restcoef;
9648  SCIP_Longint oldgcd;
9649  SCIP_Longint rest;
9650  SCIP_Longint gcd;
9651  SCIP_Bool isminsettoinfinity;
9652  SCIP_Bool ismaxsettoinfinity;
9653  SCIP_Bool isminrelax;
9654  SCIP_Bool ismaxrelax;
9655  SCIP_Bool allcoefintegral;
9656  SCIP_Bool onlybin;
9657  SCIP_Bool hasrhs;
9658  SCIP_Bool haslhs;
9659  int oldnchgcoefs;
9660  int oldnchgsides;
9661  int foundbin;
9662  int candpos;
9663  int candpos2;
9664  int offsetv;
9665  int nvars;
9666  int v;
9667  int w;
9668 
9669  assert(scip != NULL);
9670  assert(cons != NULL);
9671  assert(nchgcoefs != NULL);
9672  assert(nchgsides != NULL);
9673 
9674  /* we must not change a modifiable constraint in any way */
9675  if( SCIPconsIsModifiable(cons) )
9676  return SCIP_OKAY;
9677 
9678  if( SCIPconsIsDeleted(cons) )
9679  return SCIP_OKAY;
9680 
9681  consdata = SCIPconsGetData(cons);
9682  assert(consdata != NULL);
9683 
9684  nvars = consdata->nvars;
9685 
9686  /* do not check empty or bound-constraints */
9687  if( nvars <= 2 )
9688  return SCIP_OKAY;
9689 
9690  /* update maximal activity delta if necessary */
9691  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
9692  consdataRecomputeMaxActivityDelta(scip, consdata);
9693 
9694  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
9695  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
9696  checkMaxActivityDelta(scip, consdata);
9697 
9698  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
9699  * accordingly
9700  */
9701  /* can only work with valid non-infinity activities per variable */
9702  if( SCIPisInfinity(scip, consdata->maxactdelta) )
9703  return SCIP_OKAY;
9704 
9705  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
9706  * but the eventsystem seems to be full
9707  */
9708  consdata->normalized = FALSE;
9709 
9710  /* normalize constraint */
9711  SCIP_CALL( normalizeCons(scip, cons) );
9712  assert(consdata->normalized);
9713  assert(nvars == consdata->nvars);
9714 
9715  lhs = consdata->lhs;
9716  rhs = consdata->rhs;
9717  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
9718  assert(!SCIPisNegative(scip, rhs));
9719 
9720  if( !SCIPisInfinity(scip, -lhs) )
9721  haslhs = TRUE;
9722  else
9723  haslhs = FALSE;
9724 
9725  if( !SCIPisInfinity(scip, rhs) )
9726  hasrhs = TRUE;
9727  else
9728  hasrhs = FALSE;
9729 
9730  oldnchgcoefs = *nchgcoefs;
9731  oldnchgsides = *nchgsides;
9732 
9733  /* @todo also work on ranged rows */
9734  if( haslhs && hasrhs )
9735  {
9736  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
9737 
9738  return SCIP_OKAY;
9739  }
9740  assert(haslhs != hasrhs);
9741 
9742  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
9743  assert(!hasrhs || !SCIPisNegative(scip, rhs));
9744  assert(!haslhs || !SCIPisNegative(scip, lhs));
9745 
9746  /* get temporary memory to store the sorted permutation */
9747  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
9748 
9749  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
9750  * value of their coefficients
9751  */
9752  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
9753 
9754  /* perform sorting after permutation array */
9755  permSortConsdata(consdata, perm, nvars);
9756  consdata->sorted = FALSE;
9757  consdata->binvarssorted = FALSE;
9758 
9759  vars = consdata->vars;
9760  vals = consdata->vals;
9761  assert(vars != NULL);
9762  assert(vals != NULL);
9763  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
9764 
9765  /* free temporary memory */
9766  SCIPfreeBufferArray(scip, &perm);
9767 
9768  /* only check constraints with at least two non continuous variables */
9769  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
9770  return SCIP_OKAY;
9771 
9772  /* do not process constraints when all coefficients are 1.0 */
9773  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
9774  return SCIP_OKAY;
9775 
9776  feastol = SCIPfeastol(scip);
9777 
9778  SCIPdebugMessage("starting simplification of coeffcients\n");
9779  SCIPdebugPrintCons(scip, cons, NULL);
9780 
9781  /* get global activities */
9782  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
9783  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9784 
9785  /* cannot work with infinite activities */
9786  if( isminsettoinfinity || ismaxsettoinfinity )
9787  return SCIP_OKAY;
9788 
9789  assert(!isminrelax);
9790  assert(!ismaxrelax);
9791  assert(maxactsub > minactsub);
9792  assert(!SCIPisInfinity(scip, -minactsub));
9793  assert(!SCIPisInfinity(scip, maxactsub));
9794 
9795  v = 0;
9796  offsetv = -1;
9797  side = haslhs ? lhs : rhs;
9798 
9799  /* we now determine coefficients as large as the side of the constraint to might retrieve a better reduction were we
9800  * do not need to look at the large coefficients
9801  *
9802  * e.g. all x are binary, z are positive integer
9803  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
9804  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
9805  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
9806  *
9807  * can be changed to
9808  *
9809  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
9810  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
9811  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
9812  */
9813 
9814  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
9815  * hand side, we cannot apply the extra reduction step and need to reset v
9816  *
9817  * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 forall i is not a solution, but if we would do a change on the
9818  * coeffcients due to the gcd on the "small" coeffcients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
9819  * forall i is a solution
9820  *
9821  * also redundancy of variables would not be correct determined in such a case
9822  */
9823  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
9824  {
9825  ++v;
9826 
9827  while( SCIPisEQ(scip, side, vals[v]) )
9828  {
9829  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
9830  * extra step, which might have worked
9831  */
9832  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
9833  {
9834  v = 0;
9835  break;
9836  }
9837 
9838  ++v;
9839  assert(v < nvars);
9840  }
9841 
9842  /* cannot work with continuous variables which have a big coefficient */
9843  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
9844  return SCIP_OKAY;
9845 
9846  /* big negative coefficient, do not try to use the extra coefficient reduction step */
9847  if( SCIPisEQ(scip, side, -vals[v]) )
9848  v = 0;
9849 
9850  /* all but one variable are processed or the next variables is continuous we cannot perform the extra coefficient
9851  * reduction
9852  */
9853  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9854  v = 0;
9855 
9856  if( v > 0 )
9857  {
9858  assert(v < nvars);
9859 
9860  offsetv = v - 1;
9861 
9862  for( w = 0; w < v; ++w )
9863  {
9864  lb = SCIPvarGetLbGlobal(vars[w]);
9865  ub = SCIPvarGetUbGlobal(vars[w]);
9866 
9867  assert(vals[w] > 0);
9868 
9869  /* update residual activities */
9870  maxactsub -= ub * vals[w];
9871  minactsub -= lb * vals[w];
9872  assert(maxactsub > minactsub);
9873  }
9874  }
9875  }
9876 
9877  /* find and remove redundant variables which do not interact with the (in-)feasible of a constraints
9878  *
9879  * e.g. assume all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
9880  *
9881  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
9882  * to
9883  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
9884  */
9885  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
9886  {
9887  SCIP_Bool redundant = FALSE;
9888 
9889  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
9890  assert(gcd >= 1);
9891 
9892  if( v == 0 )
9893  {
9894  lb = SCIPvarGetLbGlobal(vars[0]);
9895  ub = SCIPvarGetUbGlobal(vars[0]);
9896 
9897  /* update residual activities */
9898  if( vals[0] > 0 )
9899  {
9900  maxactsub -= ub * vals[0];
9901  minactsub -= lb * vals[0];
9902  }
9903  else
9904  {
9905  maxactsub -= lb * vals[0];
9906  minactsub -= ub * vals[0];
9907  }
9908  assert(maxactsub > minactsub);
9909  ++v;
9910  }
9911 
9912  siderest = -SCIP_INVALID;
9913  allcoefintegral = TRUE;
9914 
9915  /* check if some variables always fit into the given constraint */
9916  for( ; v < nvars - 1; ++v )
9917  {
9918  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9919  break;
9920 
9921  if( !SCIPisIntegral(scip, vals[v]) )
9922  {
9923  allcoefintegral = FALSE;
9924  break;
9925  }
9926 
9927  /* calculate greatest common divisor for all general and binary variables */
9928  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
9929 
9930  if( gcd == 1 )
9931  break;
9932 
9933  lb = SCIPvarGetLbGlobal(vars[v]);
9934  ub = SCIPvarGetUbGlobal(vars[v]);
9935 
9936  assert(!SCIPisInfinity(scip, -lb));
9937  assert(!SCIPisInfinity(scip, ub));
9938 
9939  /* update residual activities */
9940  if( vals[v] > 0 )
9941  {
9942  maxactsub -= ub * vals[v];
9943  minactsub -= lb * vals[v];
9944  }
9945  else
9946  {
9947  maxactsub -= lb * vals[v];
9948  minactsub -= ub * vals[v];
9949  }
9950  assert(SCIPisGE(scip, maxactsub, minactsub));
9951 
9952  if( hasrhs )
9953  {
9954  /* determine the remainder of the right hand side and the gcd */
9955  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
9956  }
9957  else
9958  {
9959  /* determine the remainder of the left hand side and the gcd */
9960  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
9961  if( SCIPisZero(scip, siderest) )
9962  siderest = gcd;
9963  }
9964 
9965  /* early termination if the activities deceed the gcd */
9966  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
9967  {
9968  redundant = TRUE;
9969  break;
9970  }
9971  }
9972  assert(v < nvars || (offsetv >= 0 && gcd > 1));
9973 
9974  if( !redundant )
9975  {
9976  if( hasrhs )
9977  {
9978  /* determine the remainder of the right hand side and the gcd */
9979  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
9980  }
9981  else
9982  {
9983  /* determine the remainder of the left hand side and the gcd */
9984  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
9985  if( SCIPisZero(scip, siderest) )
9986  siderest = gcd;
9987  }
9988  }
9989  else
9990  ++v;
9991 
9992  SCIPdebugMessage("stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %"SCIP_LONGINT_FORMAT", offset position for 'side' coefficients = %d\n", v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
9993 
9994  /* check if we can remove redundant variables */
9995  if( v < nvars && (redundant ||
9996  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
9997  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
9998  {
9999  SCIP_Real oldcoef;
10000 
10001  /* double check the redundancy */
10002 #ifndef NDEBUG
10003  SCIP_Real tmpminactsub = 0.0;
10004  SCIP_Real tmpmaxactsub = 0.0;
10005 
10006  /* recompute residual activities */
10007  for( w = v; w < nvars; ++w )
10008  {
10009  lb = SCIPvarGetLbGlobal(vars[w]);
10010  ub = SCIPvarGetUbGlobal(vars[w]);
10011 
10012  assert(!SCIPisInfinity(scip, -lb));
10013  assert(!SCIPisInfinity(scip, ub));
10014 
10015  /* update residual activities */
10016  if( vals[w] > 0 )
10017  {
10018  tmpmaxactsub += ub * vals[w];
10019  tmpminactsub += lb * vals[w];
10020  }
10021  else
10022  {
10023  tmpmaxactsub += lb * vals[w];
10024  tmpminactsub += ub * vals[w];
10025  }
10026  assert(tmpmaxactsub >= tmpminactsub);
10027  }
10028 
10029  if( hasrhs )
10030  {
10031  assert(offsetv == -1);
10032 
10033  /* determine the remainder of the right hand side and the gcd */
10034  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
10035  }
10036  else
10037  {
10038  /* determine the remainder of the left hand side and the gcd */
10039  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
10040  if( SCIPisZero(scip, siderest) )
10041  siderest = gcd;
10042  }
10043 
10044  /* does the redundancy really is fulfilled */
10045  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
10046 #endif
10047 
10048  SCIPdebugMessage("removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n", nvars - v, SCIPconsGetName(cons));
10049 
10050  /* remove redundant variables */
10051  for( w = nvars - 1; w >= v; --w )
10052  {
10053  SCIP_CALL( delCoefPos(scip, cons, w) );
10054  }
10055  (*nchgcoefs) += (nvars - v);
10056 
10057  assert(w >= 0);
10058 
10059  oldcoef = vals[w];
10060 
10061  /* normalize constraint */
10062  SCIP_CALL( normalizeCons(scip, cons) );
10063  assert(vars == consdata->vars);
10064  assert(vals == consdata->vals);
10065  assert(w < consdata->nvars);
10066 
10067  /* compute new greatest common divisor due to normalization */
10068  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
10069  assert(gcd >= 1);
10070 
10071  /* update side */
10072  if( hasrhs )
10073  {
10074  /* replace old with new right hand side */
10075  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
10076  rhs = consdata->rhs;
10077  }
10078  else
10079  {
10080  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
10081  {
10082  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
10083  lhs = consdata->lhs;
10084  }
10085  else
10086  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
10087  }
10088  ++(*nchgsides);
10089 
10090  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10091  assert(!haslhs || !SCIPisNegative(scip, lhs));
10092 
10093  /* get new constraint data */
10094  nvars = consdata->nvars;
10095  assert(nvars >= 2);
10096 
10097  allcoefintegral = TRUE;
10098 
10099 #ifndef NDEBUG
10100  /* check integrality */
10101  for( w = offsetv + 1; w < nvars; ++w )
10102  {
10103  assert(SCIPisIntegral(scip, vals[w]));
10104  }
10105 #endif
10106  SCIPdebugPrintCons(scip, cons, NULL);
10107  }
10108 
10109  /* try to find a better gcd, when having large coefficients */
10110  if( offsetv >= 0 && gcd == 1 )
10111  {
10112  /* calculate greatest common divisor for all general variables */
10113  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
10114 
10115  if( gcd > 1 )
10116  {
10117  gcd = -1;
10118  candpos = -1;
10119 
10120  for( v = nvars - 1; v > offsetv; --v )
10121  {
10122  assert(!SCIPisZero(scip, vals[v]));
10123  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10124  break;
10125 
10126  if( !SCIPisIntegral(scip, vals[v]) )
10127  {
10128  allcoefintegral = FALSE;
10129  break;
10130  }
10131 
10132  oldgcd = gcd;
10133 
10134  if( gcd == -1 )
10135  {
10136  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
10137  assert(gcd >= 1);
10138  }
10139  else
10140  {
10141  /* calculate greatest common divisor for all general and binary variables */
10142  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
10143  }
10144 
10145  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
10146  * can stop searching
10147  */
10148  if( gcd == 1 )
10149  {
10150  if( !SCIPvarIsBinary(vars[v]) )
10151  break;
10152 
10153  /* found candidate */
10154  if( candpos == -1 )
10155  {
10156  gcd = oldgcd;
10157  candpos = v;
10158  }
10159  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
10160  else
10161  break;
10162  }
10163  }
10164  assert(v > offsetv || candpos > offsetv);
10165  }
10166  else
10167  candpos = -1;
10168  }
10169  else
10170  candpos = nvars - 1;
10171 
10172  /* check last coefficient for integrality */
10173  if( gcd > 1 && allcoefintegral && !redundant )
10174  {
10175  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
10176  allcoefintegral = FALSE;
10177  }
10178 
10179  /* check for further necessary coefficient adjustments */
10180  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
10181  {
10182  assert(offsetv + 1 < nvars);
10183  assert(0 <= candpos && candpos < nvars);
10184 
10185  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
10186  {
10187  SCIP_Bool notchangable = FALSE;
10188 
10189 #ifndef NDEBUG
10190  /* check integrality */
10191  for( w = offsetv + 1; w < nvars; ++w )
10192  {
10193  assert(SCIPisIntegral(scip, vals[w]));
10194  }
10195 #endif
10196 
10197  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
10198  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
10199  {
10200  /* determine the remainder of the side and the gcd */
10201  if( hasrhs )
10202  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
10203  else
10204  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
10205  assert(rest >= 0);
10206  assert(rest < gcd);
10207 
10208  /* determine the remainder of the coefficient candidate and the gcd */
10209  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
10210  assert(restcoef >= 1);
10211  assert(restcoef < gcd);
10212 
10213  if( hasrhs )
10214  {
10215  /* calculate new coefficient */
10216  if( restcoef > rest )
10217  newcoef = vals[candpos] - restcoef + gcd;
10218  else
10219  newcoef = vals[candpos] - restcoef;
10220  }
10221  else
10222  {
10223  /* calculate new coefficient */
10224  if( rest == 0 || restcoef < rest )
10225  newcoef = vals[candpos] - restcoef;
10226  else
10227  newcoef = vals[candpos] - restcoef + gcd;
10228  }
10229 
10230  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
10231  * another with the big coefficient was set to 1
10232  */
10233  if( hasrhs && SCIPisZero(scip, newcoef) )
10234  {
10235  notchangable = TRUE;
10236  }
10237  else if( SCIPisZero(scip, newcoef) )
10238  {
10239  /* delete old redundant coefficient */
10240  SCIP_CALL( delCoefPos(scip, cons, candpos) );
10241  ++(*nchgcoefs);
10242  }
10243  else
10244  {
10245  /* replace old with new coefficient */
10246  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
10247  ++(*nchgcoefs);
10248  }
10249  }
10250  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
10251  {
10252  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
10253  }
10254 
10255  /* correct side and big coefficients */
10256  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
10257  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
10258  {
10259  if( haslhs )
10260  {
10261  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
10262 
10263  SCIP_CALL( chgLhs(scip, cons, newcoef) );
10264  ++(*nchgsides);
10265  }
10266  else
10267  {
10268  assert(hasrhs);
10269  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
10270 
10271  SCIP_CALL( chgRhs(scip, cons, newcoef) );
10272  ++(*nchgsides);
10273  }
10274 
10275  /* correct coefficients up front */
10276  for( w = offsetv; w >= 0; --w )
10277  {
10278  assert(vals[w] > 0);
10279 
10280  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
10281  }
10282  (*nchgcoefs) += (offsetv + 1);
10283  }
10284 
10285  if( !notchangable )
10286  {
10287  /* normalize constraint */
10288  SCIP_CALL( normalizeCons(scip, cons) );
10289  assert(vars == consdata->vars);
10290  assert(vals == consdata->vals);
10291 
10292  /* get new constraint data */
10293  nvars = consdata->nvars;
10294  assert(nvars >= 2);
10295 
10296  SCIPdebugPrintCons(scip, cons, NULL);
10297 
10298  lhs = consdata->lhs;
10299  rhs = consdata->rhs;
10300  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10301  assert(!haslhs || !SCIPisNegative(scip, lhs));
10302  }
10303  }
10304  }
10305  }
10306 
10307  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
10308  /* no continuous variables are left over */
10309  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
10310  return SCIP_OKAY;
10311 
10312  onlybin = TRUE;
10313  allcoefintegral = TRUE;
10314  /* check if all variables are of binary type */
10315  for( v = nvars - 1; v >= 0; --v )
10316  {
10317  if( !SCIPvarIsBinary(vars[v]) )
10318  onlybin = FALSE;
10319  if( !SCIPisIntegral(scip, vals[v]) )
10320  allcoefintegral = FALSE;
10321  }
10322 
10323  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
10324  * hand side or bigger than the left hand side respectively, so we can make all of them integral
10325  *
10326  * @todo there are some steps missing ....
10327  */
10328  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
10329  {
10330  SCIP_Real val;
10331  SCIP_Real newval;
10332  SCIP_Real frac = 0.0;
10333  SCIP_Bool found = FALSE;
10334 
10335  if( hasrhs )
10336  {
10337  if( allcoefintegral )
10338  {
10339  /* replace old with new right hand side */
10340  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
10341  ++(*nchgsides);
10342  }
10343  else
10344  {
10345  siderest = rhs - SCIPfloor(scip, rhs);
10346 
10347  /* try to round down all non-integral coefficients */
10348  for( v = nvars - 1; v >= 0; --v )
10349  {
10350  val = vals[v];
10351 
10352  /* add up all possible fractional parts */
10353  if( !SCIPisIntegral(scip, val) )
10354  {
10355  lb = SCIPvarGetLbGlobal(vars[v]);
10356  ub = SCIPvarGetUbGlobal(vars[v]);
10357 
10358  /* at least one bound need to be at zero */
10359  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
10360  return SCIP_OKAY;
10361 
10362  /* swap bounds for 'standard' form */
10363  if( !SCIPisFeasZero(scip, lb) )
10364  {
10365  SCIP_Real tmp = lb;
10366  lb = ub;
10367  ub = tmp;
10368  val *= -1;
10369  }
10370 
10371  found = TRUE;
10372 
10373  frac += (val - SCIPfloor(scip, val)) * ub;
10374 
10375  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
10376  *
10377  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
10378  * x3, x4 set to 1 would be infeasible but feasible after flooring
10379  */
10380  if( SCIPisGT(scip, frac, siderest) )
10381  return SCIP_OKAY;
10382  }
10383  }
10384  assert(v == -1);
10385 
10386  SCIPdebugMessage("rounding all non-integral coefficients and the right hand side down\n");
10387 
10388  /* round rhs and coefficients to integral values */
10389  if( found )
10390  {
10391  for( v = nvars - 1; v >= 0; --v )
10392  {
10393  val = vals[v];
10394 
10395  /* add the whole fractional part */
10396  if( !SCIPisIntegral(scip, val) )
10397  {
10398  lb = SCIPvarGetLbGlobal(vars[v]);
10399 
10400  if( SCIPisFeasZero(scip, lb) )
10401  newval = SCIPfloor(scip, val);
10402  else
10403  newval = SCIPceil(scip, val);
10404 
10405  if( SCIPisZero(scip, newval) )
10406  {
10407  /* delete old redundant coefficient */
10408  SCIP_CALL( delCoefPos(scip, cons, v) );
10409  ++(*nchgcoefs);
10410  }
10411  else
10412  {
10413  /* replace old with new coefficient */
10414  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
10415  ++(*nchgcoefs);
10416  }
10417  }
10418  }
10419  }
10420 
10421  /* replace old with new right hand side */
10422  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
10423  ++(*nchgsides);
10424  }
10425  }
10426  else
10427  {
10428  if( allcoefintegral )
10429  {
10430  /* replace old with new left hand side */
10431  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
10432  ++(*nchgsides);
10433  }
10434  else
10435  {
10436  /* cannot floor left hand side to zero */
10437  if( SCIPisLT(scip, lhs, 1.0) )
10438  return SCIP_OKAY;
10439 
10440  siderest = lhs - SCIPfloor(scip, lhs);
10441 
10442  /* try to round down all non-integral coefficients */
10443  for( v = nvars - 1; v >= 0; --v )
10444  {
10445  val = vals[v];
10446 
10447  /* add up all possible fractional parts */
10448  if( !SCIPisIntegral(scip, val) )
10449  {
10450  lb = SCIPvarGetLbGlobal(vars[v]);
10451  ub = SCIPvarGetUbGlobal(vars[v]);
10452 
10453  /* at least one bound need to be at zero */
10454  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
10455  return SCIP_OKAY;
10456 
10457  /* swap bounds for 'standard' form */
10458  if( !SCIPisFeasZero(scip, lb) )
10459  {
10460  SCIP_Real tmp = lb;
10461  lb = ub;
10462  ub = tmp;
10463  val *= -1;
10464  }
10465 
10466  /* cannot floor to zero */
10467  if( SCIPisLT(scip, val, 1.0) )
10468  return SCIP_OKAY;
10469 
10470  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
10471  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
10472  return SCIP_OKAY;
10473 
10474  found = TRUE;
10475 
10476  frac += (val - SCIPfloor(scip, val)) * ub;
10477 
10478  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
10479  * fractional parts of the variables, we cannot tighten the coefficients
10480  *
10481  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
10482  * x2-x4 set to 1 would be feasible but not after flooring
10483  */
10484  if( SCIPisGE(scip, frac, 1 + siderest) )
10485  return SCIP_OKAY;
10486  }
10487  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
10488  else
10489  return SCIP_OKAY;
10490  }
10491  assert(v == -1);
10492 
10493  SCIPdebugMessage("rounding all non-integral coefficients and the left hand side down\n");
10494 
10495  /* round lhs and coefficients to integral values */
10496  if( found )
10497  {
10498  for( v = nvars - 1; v >= 0; --v )
10499  {
10500  val = vals[v];
10501 
10502  /* add the whole fractional part */
10503  if( !SCIPisIntegral(scip, val) )
10504  {
10505  lb = SCIPvarGetLbGlobal(vars[v]);
10506 
10507  if( SCIPisFeasZero(scip, lb) )
10508  newval = SCIPfloor(scip, val);
10509  else
10510  newval = SCIPceil(scip, val);
10511 
10512  if( SCIPisZero(scip, newval) )
10513  {
10514  /* delete old redundant coefficient */
10515  SCIP_CALL( delCoefPos(scip, cons, v) );
10516  ++(*nchgcoefs);
10517  }
10518  else
10519  {
10520  /* replace old with new coefficient */
10521  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
10522  ++(*nchgcoefs);
10523  }
10524  }
10525  }
10526  }
10527 
10528  /* replace old with new left hand side */
10529  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
10530  ++(*nchgsides);
10531  }
10532  }
10533 
10534  /* normalize constraint */
10535  SCIP_CALL( normalizeCons(scip, cons) );
10536  assert(vars == consdata->vars);
10537  assert(vals == consdata->vals);
10538 
10539  rhs = consdata->rhs;
10540  lhs = consdata->lhs;
10541 
10542  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10543  assert(!haslhs || !SCIPisNegative(scip, lhs));
10544 
10545  SCIPdebugPrintCons(scip, cons, NULL);
10546 
10547  nvars = consdata->nvars;
10548  if( nvars < 2 )
10549  return SCIP_OKAY;
10550 
10551  allcoefintegral = TRUE;
10552 #ifndef NDEBUG
10553  /* debug check if all coefficients are really integral */
10554  for( v = nvars - 1; v >= 0; --v )
10555  assert(SCIPisIntegral(scip, vals[v]));
10556 #endif
10557  }
10558 
10559  /* @todo following can also work on non integral coefficients, need more investigation */
10560  /* only check constraints with integral coefficients on all integral variables */
10561  if( !allcoefintegral )
10562  return SCIP_OKAY;
10563 
10564  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
10565  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
10566  return SCIP_OKAY;
10567 
10568  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
10569  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
10570  return SCIP_OKAY;
10571 
10572  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
10573  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
10574  return SCIP_OKAY;
10575 
10576  assert(nvars >= 2);
10577 
10578  /* start gcd procedure for all variables */
10579 
10580  do
10581  {
10582  oldnchgcoefs = *nchgcoefs;
10583  oldnchgsides = *nchgsides;
10584 
10585  /* stop if we have two coeffcients which are one in absolute value */
10586  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
10587  return SCIP_OKAY;
10588 
10589  gcd = -1;
10590 
10591  /* calculate greatest common divisor over all integer variables */
10592  if( !onlybin )
10593  {
10594  foundbin = -1;
10595 
10596  for( v = nvars - 1; v >= 0; --v )
10597  {
10598  assert(!SCIPisZero(scip, vals[v]));
10599  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
10600 
10601  if( SCIPvarIsBinary(vars[v]) )
10602  {
10603  if( foundbin == -1 )
10604  foundbin = v;
10605  continue;
10606  }
10607 
10608  absval = REALABS(vals[v]);
10609  assert(SCIPisIntegral(scip, absval));
10610 
10611  if( gcd == -1 )
10612  {
10613  gcd = (SCIP_Longint)(absval + feastol);
10614  assert(gcd >= 1);
10615  }
10616  else
10617  {
10618  /* calculate greatest common divisor for all general variables */
10619  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
10620  }
10621  if( gcd == 1 )
10622  break;
10623  }
10624  }
10625  else
10626  foundbin = nvars - 1;
10627 
10628  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
10629  if( gcd == 1 || foundbin == -1)
10630  return SCIP_OKAY;
10631 
10632  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
10633 
10634  candpos = -1;
10635  candpos2 = -1;
10636 
10637  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
10638  * change the coefficient
10639  */
10640  for( v = foundbin; v >= 0; --v )
10641  {
10642  if( onlybin || SCIPvarIsBinary(vars[v]) )
10643  {
10644  absval = REALABS(vals[v]);
10645  assert(SCIPisIntegral(scip, absval));
10646 
10647  oldgcd = gcd;
10648 
10649  if( gcd == -1 )
10650  {
10651  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
10652  assert(gcd >= 1);
10653  }
10654  else
10655  {
10656  /* calculate greatest common divisor for all general and binary variables */
10657  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
10658  }
10659 
10660  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
10661  * can terminate
10662  */
10663  if( gcd == 1 )
10664  {
10665  /* found candidate */
10666  if( candpos == -1 )
10667  {
10668  gcd = oldgcd;
10669  candpos = v;
10670 
10671  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
10672  * the coefficient change
10673  */
10674  if( onlybin && v == foundbin - 1 )
10675  candpos2 = foundbin;
10676  }
10677  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
10678  else
10679  {
10680  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
10681  {
10682  assert(candpos2 == nvars - 1);
10683 
10684  /* take new candidates */
10685  candpos = candpos2;
10686 
10687  /* recalculate gcd from scratch */
10688  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
10689  assert(gcd >= 1);
10690 
10691  /* calculate greatest common divisor for all general and binary variables */
10692  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
10693  if( gcd == 1 )
10694  return SCIP_OKAY;
10695  }
10696  else
10697  /* cannot determine a possible coefficient for reduction */
10698  return SCIP_OKAY;
10699  }
10700  }
10701  }
10702  }
10703  assert(gcd >= 2);
10704 
10705  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
10706  * further
10707  */
10708  assert(candpos >= 0 && candpos < nvars);
10709 
10710  /* all variables and all coefficients are integral, so the side should be too */
10711  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
10712 
10713  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
10714  * @see normalizeCons()
10715  */
10716  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10717  assert(!haslhs || !SCIPisNegative(scip, lhs));
10718 
10719  /* determine the remainder of the side and the gcd */
10720  if( hasrhs )
10721  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
10722  else
10723  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
10724  assert(rest >= 0);
10725  assert(rest < gcd);
10726 
10727  /* determine the remainder of the coefficient candidate and the gcd */
10728  if( vals[candpos] < 0 )
10729  {
10730  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
10731  assert(restcoef <= -1);
10732  restcoef += gcd;
10733  }
10734  else
10735  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
10736  assert(restcoef >= 1);
10737  assert(restcoef < gcd);
10738 
10739  if( hasrhs )
10740  {
10741  if( rest > 0 )
10742  {
10743  /* replace old with new right hand side */
10744  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
10745  ++(*nchgsides);
10746  }
10747 
10748  /* calculate new coefficient */
10749  if( restcoef > rest )
10750  newcoef = vals[candpos] - restcoef + gcd;
10751  else
10752  newcoef = vals[candpos] - restcoef;
10753  }
10754  else
10755  {
10756  if( rest > 0 )
10757  {
10758  /* replace old with new left hand side */
10759  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
10760  ++(*nchgsides);
10761  }
10762 
10763  /* calculate new coefficient */
10764  if( rest == 0 || restcoef < rest )
10765  newcoef = vals[candpos] - restcoef;
10766  else
10767  newcoef = vals[candpos] - restcoef + gcd;
10768  }
10769  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
10770 
10771  SCIPdebugMessage("gcd = %"SCIP_LONGINT_FORMAT", rest = %"SCIP_LONGINT_FORMAT", restcoef = %"SCIP_LONGINT_FORMAT"; changing coef of variable <%s> to %g and %s by %"SCIP_LONGINT_FORMAT"\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
10772 
10773  if( SCIPisZero(scip, newcoef) )
10774  {
10775  /* delete redundant coefficient */
10776  SCIP_CALL( delCoefPos(scip, cons, candpos) );
10777  }
10778  else
10779  {
10780  /* replace old with new coefficient */
10781  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
10782  }
10783  ++(*nchgcoefs);
10784 
10785  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
10786  SCIP_CALL( normalizeCons(scip, cons) );
10787  assert(vars == consdata->vars);
10788  assert(vals == consdata->vals);
10789 
10790  SCIPdebugPrintCons(scip, cons, NULL);
10791 
10792  rhs = consdata->rhs;
10793  lhs = consdata->lhs;
10794  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10795  assert(!haslhs || !SCIPisNegative(scip, lhs));
10796 
10797  nvars = consdata->nvars;
10798 
10799  SCIPdebugMessage("we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
10800  }
10801  while( nvars >= 2 );
10802 
10803  return SCIP_OKAY;
10804 }
10805 
10806 
10807 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
10808  * cons0 := a * cons0 + b * cons1,
10809  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
10810  * for numerical stability, we will only accept integral a and b;
10811  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
10812  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
10813  */
10814 static
10816  SCIP* scip, /**< SCIP data structure */
10817  SCIP_CONS* cons0, /**< (in)equality to modify */
10818  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
10819  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
10820  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
10821  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
10822  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
10823  int nvarscommon, /**< number of variables, that appear in both constraints */
10824  int commonidxweight, /**< variable weight sum of common variables */
10825  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
10826  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
10827  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
10828  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
10829  SCIP_Bool* aggregated /**< pointer to store whether an aggregation was made */
10830  )
10831 {
10832  SCIP_CONSDATA* consdata0;
10833  SCIP_CONSDATA* consdata1;
10834  SCIP_Real a;
10835  SCIP_Real b;
10836  SCIP_Real aggrcoef;
10837  SCIP_Real scalarsum;
10838  SCIP_Real bestscalarsum;
10839  SCIP_Bool betterscalarsum;
10840  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
10841  int varweight;
10842  int nvars;
10843  int bestvarweight;
10844  int bestnvars;
10845  int bestv;
10846  int v;
10847  int i;
10848 
10849  assert(scip != NULL);
10850  assert(cons0 != NULL);
10851  assert(cons1 != NULL);
10852  assert(commonidx0 != NULL);
10853  assert(commonidx1 != NULL);
10854  assert(diffidx0minus1 != NULL);
10855  assert(diffidx1minus0 != NULL);
10856  assert(nvarscommon >= 1);
10857  assert(commonidxweight >= nvarscommon);
10858  assert(nchgcoefs != NULL);
10859  assert(aggregated != NULL);
10860 
10861  assert(SCIPconsIsActive(cons0));
10862  assert(SCIPconsIsActive(cons1));
10863 
10864  SCIPdebugMessage("try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
10865 
10866  /* cons0 is an (in)equality */
10867  consdata0 = SCIPconsGetData(cons0);
10868  assert(consdata0 != NULL);
10869  assert(consdata0->nvars >= 1);
10870  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
10871  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
10872 
10873  /* cons1 is an equality */
10874  consdata1 = SCIPconsGetData(cons1);
10875  assert(consdata1 != NULL);
10876  assert(consdata1->nvars >= 1);
10877  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
10878  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
10879 
10880  *aggregated = FALSE;
10881 
10882  /* search for the best common variable such that
10883  * val1[var] * consdata0 - val0[var] * consdata1
10884  * has least weighted number of variables
10885  */
10886  bestvarweight = commonidxweight + diffidx0minus1weight;
10887  bestnvars = consdata0->nvars;
10888  bestv = -1;
10889  bestscalarsum = 0.0;
10890  commonvarlindependent = TRUE;
10891  for( v = 0; v < nvarscommon; ++v )
10892  {
10893  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
10894  a = consdata1->vals[commonidx1[v]];
10895  b = -consdata0->vals[commonidx0[v]];
10896 
10897  /* only try aggregation, if coefficients are integral (numerical stability) */
10898  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
10899  {
10900  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
10901  varweight = diffidx0minus1weight + diffidx1minus0weight;
10902  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
10903  scalarsum = REALABS(a) + REALABS(b);
10904  betterscalarsum = (scalarsum < bestscalarsum);
10905  for( i = 0; i < nvarscommon
10906  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
10907  {
10908  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
10909  if( !SCIPisZero(scip, aggrcoef) )
10910  {
10911  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
10912  nvars++;
10913  }
10914  }
10915  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
10916  {
10917  bestv = v;
10918  bestvarweight = varweight;
10919  bestnvars = nvars;
10920  bestscalarsum = scalarsum;
10921  }
10922  }
10923 
10924  /* update commonvarlindependent flag, if still TRUE:
10925  * 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
10926  */
10927  if( commonvarlindependent && v > 0 )
10928  commonvarlindependent = SCIPisEQ(scip,
10929  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
10930  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
10931  }
10932 
10933  /* if better aggregation was found, create new constraint and delete old one */
10934  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
10935  {
10936  SCIP_CONS* newcons;
10937  SCIP_CONSDATA* newconsdata;
10938  SCIP_VAR** newvars;
10939  SCIP_Real* newvals;
10940  SCIP_Real newlhs;
10941  SCIP_Real newrhs;
10942  int newnvars;
10943 
10944  if( bestv != -1 )
10945  {
10946  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
10947  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
10948  {
10949  a = consdata1->vals[commonidx1[bestv]];
10950  b = -consdata0->vals[commonidx0[bestv]];
10951  }
10952  else
10953  {
10954  a = -consdata1->vals[commonidx1[bestv]];
10955  b = consdata0->vals[commonidx0[bestv]];
10956  }
10957  assert(SCIPisIntegral(scip, a));
10958  assert(SCIPisPositive(scip, a));
10959  assert(SCIPisIntegral(scip, b));
10960  assert(!SCIPisZero(scip, b));
10961  }
10962  else
10963  {
10964  assert(commonvarlindependent);
10965  if( consdata1->vals[commonidx1[0]] > 0.0 )
10966  {
10967  a = consdata1->vals[commonidx1[0]];
10968  b = -consdata0->vals[commonidx0[0]];
10969  }
10970  else
10971  {
10972  a = -consdata1->vals[commonidx1[0]];
10973  b = consdata0->vals[commonidx0[0]];
10974  }
10975  assert(SCIPisPositive(scip, a));
10976  assert(!SCIPisZero(scip, b));
10977 
10978  /* if a/b is integral, then we can easily choose integer multipliers */
10979  if( SCIPisIntegral(scip, a/b) )
10980  {
10981  if( a/b > 0 )
10982  {
10983  a /= b;
10984  b = 1.0;
10985  }
10986  else
10987  {
10988  a /= -b;
10989  b = -1.0;
10990  }
10991  }
10992 
10993  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
10994  bestvarweight = diffidx0minus1weight + diffidx1minus0weight;
10995  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
10996  }
10997 
10998  SCIPdebugMessage("aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
10999  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
11000  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
11001  SCIPdebugPrintCons(scip, cons0, NULL);
11002  SCIPdebugPrintCons(scip, cons1, NULL);
11003 
11004  /* get temporary memory for creating the new linear constraint */
11005  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
11006  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
11007 
11008  /* calculate the common coefficients, if we have not recognized linear dependency */
11009  newnvars = 0;
11010  if( !commonvarlindependent )
11011  {
11012  for( i = 0; i < nvarscommon; ++i )
11013  {
11014  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
11015  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
11016 
11017  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
11018  if( !SCIPisZero(scip, aggrcoef) )
11019  {
11020  assert(newnvars < bestnvars);
11021  newvars[newnvars] = consdata0->vars[commonidx0[i]];
11022  newvals[newnvars] = aggrcoef;
11023  newnvars++;
11024  }
11025  }
11026  }
11027  else
11028  {
11029  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
11030 #ifndef NDEBUG
11031  for( i = 0; i < nvarscommon; ++i )
11032  {
11033  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
11034  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
11035 
11036  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
11037  assert(SCIPisZero(scip, aggrcoef));
11038  }
11039 #endif
11040  }
11041 
11042  /* calculate the coefficients appearing in cons0 but not in cons1 */
11043  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
11044  {
11045  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
11046 
11047  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
11048  assert(!SCIPisZero(scip, aggrcoef));
11049  assert(newnvars < bestnvars);
11050  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
11051  newvals[newnvars] = aggrcoef;
11052  newnvars++;
11053  }
11054 
11055  /* calculate the coefficients appearing in cons1 but not in cons0 */
11056  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
11057  {
11058  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
11059 
11060  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
11061  assert(!SCIPisZero(scip, aggrcoef));
11062  assert(newnvars < bestnvars);
11063  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
11064  newvals[newnvars] = aggrcoef;
11065  newnvars++;
11066  }
11067  assert(newnvars == bestnvars);
11068 
11069  /* calculate the new left and right hand side of the (in)equality */
11070  assert(!SCIPisInfinity(scip, -consdata1->lhs));
11071  assert(!SCIPisInfinity(scip, consdata1->rhs));
11072  if( SCIPisInfinity(scip, -consdata0->lhs) )
11073  newlhs = -SCIPinfinity(scip);
11074  else
11075  newlhs = a * consdata0->lhs + b * consdata1->lhs;
11076  if( SCIPisInfinity(scip, consdata0->rhs) )
11077  newrhs = SCIPinfinity(scip);
11078  else
11079  newrhs = a * consdata0->rhs + b * consdata1->rhs;
11080 
11081  /* create the new linear constraint */
11082  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
11084  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
11085  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
11087 
11088  newconsdata = SCIPconsGetData(newcons);
11089  assert(newconsdata != NULL);
11090 
11091  /* copy the upgraded flag from the old cons0 to the new constraint */
11092  newconsdata->upgraded = consdata0->upgraded;
11093 
11094  /* normalize the new constraint */
11095  SCIP_CALL( normalizeCons(scip, newcons) );
11096 
11097  /* check, if we really want to use the new constraint instead of the old one:
11098  * use the new one, if the maximum norm doesn't grow too much
11099  */
11100  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
11101  {
11102  SCIPdebugMessage(" -> aggregated to <%s>\n", SCIPconsGetName(newcons));
11103  SCIPdebugPrintCons(scip, newcons, NULL);
11104 
11105  /* update the statistics: we changed all coefficients */
11106  if( !consdata0->upgraded )
11107  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
11108  *aggregated = TRUE;
11109 
11110  /* delete the old constraint, and add the new linear constraint to the problem */
11111  SCIP_CALL( SCIPdelCons(scip, cons0) );
11112  SCIP_CALL( SCIPaddCons(scip, newcons) );
11113  }
11114 
11115  /* release the new constraint */
11116  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
11117 
11118  /* free temporary memory */
11119  SCIPfreeBufferArray(scip, &newvals);
11120  SCIPfreeBufferArray(scip, &newvars);
11121  }
11122 
11123  return SCIP_OKAY;
11124 }
11125 
11126 /** gets the key of the given element */
11127 static
11128 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
11129 { /*lint --e{715}*/
11130  /* the key is the element itself */
11131  return elem;
11132 }
11133 
11134 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
11135  * coefficients are either equal or negated
11136  */
11137 static
11138 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
11139 {
11140  SCIP* scip;
11141  SCIP_CONSDATA* consdata1;
11142  SCIP_CONSDATA* consdata2;
11143  SCIP_Bool coefsequal;
11144  SCIP_Bool coefsnegated;
11145  int i;
11146 
11147  assert(key1 != NULL);
11148  assert(key2 != NULL);
11149  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
11150  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
11151  assert(consdata1->sorted);
11152  assert(consdata2->sorted);
11153 
11154  scip = (SCIP*)userptr;
11155  assert(scip != NULL);
11156 
11157  /* checks trivial case */
11158  if( consdata1->nvars != consdata2->nvars )
11159  return FALSE;
11160 
11161  coefsequal = TRUE;
11162  coefsnegated = TRUE;
11163 
11164  for( i = 0; i < consdata1->nvars && (coefsequal || coefsnegated); ++i )
11165  {
11166  SCIP_Real val1;
11167  SCIP_Real val2;
11168 
11169  /* tests if variables are equal */
11170  if( consdata1->vars[i] != consdata2->vars[i] )
11171  {
11172  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
11173  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
11174  coefsequal = FALSE;
11175  coefsnegated = FALSE;
11176  break;
11177  }
11178  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
11179 
11180  /* tests if coefficients are either equal or negated */
11181  val1 = consdata1->vals[i];
11182  val2 = consdata2->vals[i];
11183  coefsequal = coefsequal && SCIPisEQ(scip, val1, val2);
11184  coefsnegated = coefsnegated && SCIPisEQ(scip, val1, -val2);
11185  }
11186 
11187  return (coefsequal || coefsnegated);
11188 }
11189 
11190 #define MULTIPLIER 2048
11191 /** returns the hash value of the key */
11192 static
11193 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
11194 {
11195  SCIP_CONSDATA* consdata;
11196  SCIP_Real maxabsrealval;
11197  unsigned int hashval;
11198  int minidx;
11199  int mididx;
11200  int maxidx;
11201  int addval;
11202 #ifndef NDEBUG
11203  SCIP* scip;
11205  scip = (SCIP*)userptr;
11206  assert(scip != NULL);
11207 #endif
11208 
11209  assert(key != NULL);
11210  consdata = SCIPconsGetData((SCIP_CONS*)key);
11211  assert(consdata != NULL);
11212  assert(consdata->nvars > 0);
11213 
11214  assert(consdata->sorted);
11215 
11216  minidx = SCIPvarGetIndex(consdata->vars[0]);
11217  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
11218  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
11219  assert(minidx >= 0 && minidx <= maxidx);
11220 
11221  addval = (int) REALABS(consdata->vals[0]);
11222  addval += (((int) REALABS(consdata->vals[consdata->nvars / 2])) << 4); /*lint !e701*/
11223  addval += (((int) REALABS(consdata->vals[consdata->nvars - 1])) << 8); /*lint !e701*/
11224 
11225  maxabsrealval = consdataGetMaxAbsval(consdata);
11226  /* hash value depends on vectors of variable indices */
11227  if( maxabsrealval < (SCIP_Real) INT_MAX )
11228  {
11229  if( maxabsrealval < 1.0 )
11230  addval += (int) (MULTIPLIER * maxabsrealval);
11231  else
11232  addval += (int) maxabsrealval;
11233  }
11234 
11235  hashval = (consdata->nvars << 29) + (minidx << 22) + (mididx << 11) + maxidx + addval; /*lint !e701*/
11236 
11237  return hashval;
11238 }
11239 
11240 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
11241  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
11242  */
11243 static
11245  SCIP* scip, /**< SCIP data structure */
11246  BMS_BLKMEM* blkmem, /**< block memory */
11247  SCIP_CONS** conss, /**< constraint set */
11248  int nconss, /**< number of constraints in constraint set */
11249  int* firstchange, /**< pointer to store first changed constraint */
11250  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11251  int* ndelconss, /**< pointer to count number of deleted constraints */
11252  int* nchgsides /**< pointer to count number of changed left/right hand sides */
11253  )
11254 {
11255  SCIP_HASHTABLE* hashtable;
11256  int hashtablesize;
11257  int c;
11259  assert(scip != NULL);
11260  assert(blkmem != NULL);
11261  assert(conss != NULL);
11262  assert(firstchange != NULL);
11263  assert(cutoff != NULL);
11264  assert(ndelconss != NULL);
11265  assert(nchgsides != NULL);
11266 
11267  /* create a hash table for the constraint set */
11268  hashtablesize = SCIPcalcHashtableSize(10*nconss);
11269  hashtablesize = MAX(hashtablesize, HASHSIZE_LINEARCONS);
11270  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
11271  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
11272 
11273  /* check all constraints in the given set for redundancy */
11274  for( c = 0; c < nconss; ++c )
11275  {
11276  SCIP_CONS* cons0;
11277  SCIP_CONS* cons1;
11278  SCIP_CONSDATA* consdata0;
11279 
11280  cons0 = conss[c];
11281 
11282  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
11283  continue;
11284 
11285  /* check for interuption */
11286  if( c % 1000 == 0 && SCIPisStopped(scip) )
11287  break;
11288 
11289  /* sorts the constraint */
11290  consdata0 = SCIPconsGetData(cons0);
11291  assert(consdata0 != NULL);
11292  SCIP_CALL( consdataSort(scip, consdata0) );
11293  assert(consdata0->sorted);
11294 
11295  /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
11296  * to the ones of cons0 */
11297  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
11298 
11299  if( cons1 != NULL )
11300  {
11301  SCIP_CONS* consstay;
11302  SCIP_CONS* consdel;
11303  SCIP_CONSDATA* consdatastay;
11304  SCIP_CONSDATA* consdatadel;
11305  SCIP_CONSDATA* consdata1;
11306 
11307  SCIP_Real lhs;
11308  SCIP_Real rhs;
11309 
11310  assert(SCIPconsIsActive(cons1));
11311  assert(!SCIPconsIsModifiable(cons1));
11312 
11313  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
11314  * delete old constraints afterwards
11315  */
11316  consdata1 = SCIPconsGetData(cons1);
11317 
11318  assert(consdata1 != NULL);
11319  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
11320 
11321  assert(consdata1->sorted);
11322  assert(consdata0->vars[0] == consdata1->vars[0]);
11323 
11324  if( SCIPisEQ(scip, consdata0->vals[0], consdata1->vals[0]) )
11325  {
11326  /* the coefficients of both constraints are equal */
11327  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], consdata1->vals[1]));
11328  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
11329  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11330  SCIPdebugPrintCons(scip, cons0, NULL);
11331  SCIPdebugPrintCons(scip, cons1, NULL);
11332 
11333  lhs = MAX(consdata1->lhs, consdata0->lhs);
11334  rhs = MIN(consdata1->rhs, consdata0->rhs);
11335  }
11336  else
11337  {
11338  /* the coefficients of both rows are negations */
11339  assert(SCIPisEQ(scip, consdata0->vals[0], -(consdata1->vals[0])));
11340  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], -(consdata1->vals[1])));
11341  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
11342  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11343  SCIPdebugPrintCons(scip, cons0, NULL);
11344  SCIPdebugPrintCons(scip, cons1, NULL);
11345 
11346  lhs = MAX(consdata1->lhs, -consdata0->rhs);
11347  rhs = MIN(consdata1->rhs, -consdata0->lhs);
11348  }
11349 
11350  if( SCIPisFeasLT(scip, rhs, lhs) )
11351  {
11352  SCIPdebugMessage("aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons1));
11353  *cutoff = TRUE;
11354  break;
11355  }
11356 
11357  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
11358  if( lhs > rhs )
11359  {
11360  rhs = (lhs + rhs)/2;
11361  lhs = rhs;
11362  }
11363 
11364  /* check which constraint has to stay;
11365  * changes applied to an upgraded constraint will not be considered in the instance */
11366  if( consdata1->upgraded && !consdata0->upgraded )
11367  {
11368  consstay = cons0;
11369  consdatastay = consdata0;
11370  consdel = cons1;
11371  consdatadel = consdata1;
11372 
11373  /* exchange consdel with consstay in hashtable */
11374  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) consdel) );
11375  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) consstay) );
11376  }
11377  else
11378  {
11379  consstay = cons1;
11380  consdatastay = consdata1;
11381  consdel = cons0;
11382  consdatadel = consdata0;
11383  }
11384 
11385  /* update lhs and rhs of consstay */
11386  SCIP_CALL( chgLhs(scip, consstay, lhs) );
11387  SCIP_CALL( chgRhs(scip, consstay, rhs) );
11388 
11389  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11390  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
11391 
11392  /* delete consdel */
11393  assert(!consdatastay->upgraded || (consdatastay->upgraded && consdatadel->upgraded));
11394  SCIP_CALL( SCIPdelCons(scip, consdel) );
11395  if( !consdatadel->upgraded )
11396  (*ndelconss)++;
11397 
11398  /* update the first changed constraint to begin the next aggregation round with */
11399  if( consdatastay->changed && SCIPconsGetPos(consstay) < *firstchange )
11400  *firstchange = SCIPconsGetPos(consstay);
11401 
11402  assert(SCIPconsIsActive(consstay));
11403  }
11404  else
11405  {
11406  /* no such constraint in current hash table: insert cons0 into hash table */
11407  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
11408  }
11409  }
11410 #ifdef SCIP_MORE_DEBUG
11411  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
11413 #endif
11414 
11415  /* free hash table */
11416  SCIPhashtableFree(&hashtable);
11417 
11418  return SCIP_OKAY;
11419 }
11420 
11421 /** compares constraint with all prior constraints for possible redundancy or aggregation,
11422  * and removes or changes constraint accordingly
11423  */
11424 static
11426  SCIP* scip, /**< SCIP data structure */
11427  SCIP_CONS** conss, /**< constraint set */
11428  int firstchange, /**< first constraint that changed since last pair preprocessing round */
11429  int chkind, /**< index of constraint to check against all prior indices upto startind */
11430  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
11431  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11432  int* ndelconss, /**< pointer to count number of deleted constraints */
11433  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
11434  int* nchgcoefs /**< pointer to count number of changed coefficients */
11435  )
11436 {
11437  SCIP_CONS* cons0;
11438  SCIP_CONSDATA* consdata0;
11439  int* commonidx0;
11440  int* commonidx1;
11441  int* diffidx0minus1;
11442  int* diffidx1minus0;
11443  SCIP_Longint possignature0;
11444  SCIP_Longint negsignature0;
11445  SCIP_Bool cons0changed;
11446  SCIP_Bool cons0isequality;
11447  int diffidx1minus0size;
11448  int c;
11449  SCIP_Real cons0lhs;
11450  SCIP_Real cons0rhs;
11451  SCIP_Bool cons0upgraded;
11452 
11453  assert(scip != NULL);
11454  assert(conss != NULL);
11455  assert(firstchange <= chkind);
11456  assert(cutoff != NULL);
11457  assert(ndelconss != NULL);
11458  assert(nchgsides != NULL);
11459  assert(nchgcoefs != NULL);
11460 
11461  /* get the constraint to be checked against all prior constraints */
11462  cons0 = conss[chkind];
11463  assert(cons0 != NULL);
11464  assert(SCIPconsIsActive(cons0));
11465  assert(!SCIPconsIsModifiable(cons0));
11466 
11467  consdata0 = SCIPconsGetData(cons0);
11468  assert(consdata0 != NULL);
11469  assert(consdata0->nvars >= 1);
11470  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
11471 
11472  /* sort the constraint */
11473  SCIP_CALL( consdataSort(scip, consdata0) );
11474 
11475  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
11476  consdataCalcSignatures(consdata0);
11477  possignature0 = consdata0->possignature;
11478  negsignature0 = consdata0->negsignature;
11479 
11480  /* get temporary memory for indices of common variables */
11481  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
11482  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
11483  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
11484  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
11485  diffidx1minus0size = consdata0->nvars;
11486 
11487  cons0lhs = consdata0->lhs;
11488  cons0rhs = consdata0->rhs;
11489  cons0upgraded = consdata0->upgraded;
11490 
11491  /* check constraint against all prior constraints */
11492  cons0changed = consdata0->changed;
11493  consdata0->changed = FALSE;
11494  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
11495  {
11496  SCIP_CONS* cons1;
11497  SCIP_CONSDATA* consdata1;
11498  SCIP_Longint possignature1;
11499  SCIP_Longint negsignature1;
11500  SCIP_Bool cons0dominateslhs;
11501  SCIP_Bool cons1dominateslhs;
11502  SCIP_Bool cons0dominatesrhs;
11503  SCIP_Bool cons1dominatesrhs;
11504  SCIP_Bool cons1isequality;
11505  SCIP_Bool coefsequal;
11506  SCIP_Bool coefsnegated;
11507  SCIP_Bool tryaggregation;
11508  int nvarscommon;
11509  int nvars0minus1;
11510  int nvars1minus0;
11511  int commonidxweight;
11512  int diffidx0minus1weight;
11513  int diffidx1minus0weight;
11514  int v0;
11515  int v1;
11516 
11517  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
11518  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
11519  assert(cons0upgraded == consdata0->upgraded);
11520 
11521  cons1 = conss[c];
11522 
11523  /* cons1 has become inactive during presolving of constraint pairs */
11524  if( cons1 == NULL )
11525  continue;
11526 
11527  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
11528  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
11529 
11530  consdata1 = SCIPconsGetData(cons1);
11531  assert(consdata1 != NULL);
11532 
11533  /* SCIPdebugMessage("preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
11534  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
11535  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
11536 
11537  /* if both constraints didn't change since last pair processing, we can ignore the pair */
11538  if( !cons0changed && !consdata1->changed )
11539  continue;
11540 
11541  /* if both constraints are already upgraded, skip the pair;
11542  * because changes on these constraints cannot be applied to the instance anymore */
11543  if( cons0upgraded && consdata1->upgraded )
11544  continue;
11545 
11546  assert(consdata1->nvars >= 1);
11547 
11548  /* sort the constraint */
11549  SCIP_CALL( consdataSort(scip, consdata1) );
11550 
11551  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
11552  consdataCalcSignatures(consdata1);
11553  possignature1 = consdata1->possignature;
11554  negsignature1 = consdata1->negsignature;
11555 
11556  /* the signatures give a quick test to check for domination and equality of coefficients */
11557  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
11558  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
11559  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
11560  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
11561  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
11562  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
11563  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
11564  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
11565  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
11566  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
11567  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
11568  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
11569  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
11570  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
11571  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
11572  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
11573  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
11574  && !coefsequal && !coefsnegated && !tryaggregation )
11575  continue;
11576 
11577  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
11578  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
11579  {
11580  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
11581  diffidx1minus0size = consdata1->nvars;
11582  }
11583 
11584  /* check consdata0 against consdata1:
11585  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
11586  * consdata0 dominates consdata1 w.r.t. left hand side
11587  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
11588  * consdata0 dominates consdata1 w.r.t. right hand side
11589  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
11590  * ranged row (or equality)
11591  * - if at least one constraint is an equality, count the weighted number of common variables W_c
11592  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
11593  * where the weight of each variable depends on its type, such that aggregations in order to remove the
11594  * number of continuous and integer variables are preferred:
11595  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
11596  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
11597  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
11598  * to be positive to not switch the sense of the (in)equality cons0
11599  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
11600  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
11601  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
11602  * to be positive to not switch the sense of the (in)equality cons1
11603  */
11604 
11605  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
11606  nvarscommon = 0;
11607  commonidxweight = 0;
11608  nvars0minus1 = 0;
11609  diffidx0minus1weight = 0;
11610  nvars1minus0 = 0;
11611  diffidx1minus0weight = 0;
11612  v0 = 0;
11613  v1 = 0;
11614  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
11615  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
11616  || coefsequal || coefsnegated || tryaggregation) )
11617  {
11618  SCIP_VAR* var;
11619  SCIP_Real val0;
11620  SCIP_Real val1;
11621  int varcmp;
11622 
11623  /* test, if variable appears in only one or in both constraints */
11624  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
11625  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
11626  else if( v0 < consdata0->nvars )
11627  varcmp = -1;
11628  else
11629  varcmp = +1;
11630 
11631  switch( varcmp )
11632  {
11633  case -1:
11634  /* variable doesn't appear in consdata1 */
11635  var = consdata0->vars[v0];
11636  val0 = consdata0->vals[v0];
11637  val1 = 0.0;
11638  if( tryaggregation )
11639  {
11640  diffidx0minus1[nvars0minus1] = v0;
11641  nvars0minus1++;
11642  diffidx0minus1weight += getVarWeight(var);
11643  }
11644  v0++;
11645  coefsequal = FALSE;
11646  coefsnegated = FALSE;
11647  break;
11648 
11649  case +1:
11650  /* variable doesn't appear in consdata0 */
11651  var = consdata1->vars[v1];
11652  val0 = 0.0;
11653  val1 = consdata1->vals[v1];
11654  if( tryaggregation )
11655  {
11656  diffidx1minus0[nvars1minus0] = v1;
11657  nvars1minus0++;
11658  diffidx1minus0weight += getVarWeight(var);
11659  }
11660  v1++;
11661  coefsequal = FALSE;
11662  coefsnegated = FALSE;
11663  break;
11664 
11665  case 0:
11666  /* variable appears in both constraints */
11667  assert(consdata0->vars[v0] == consdata1->vars[v1]);
11668  var = consdata0->vars[v0];
11669  val0 = consdata0->vals[v0];
11670  val1 = consdata1->vals[v1];
11671  if( tryaggregation )
11672  {
11673  commonidx0[nvarscommon] = v0;
11674  commonidx1[nvarscommon] = v1;
11675  nvarscommon++;
11676  commonidxweight += getVarWeight(var);
11677  }
11678  v0++;
11679  v1++;
11680  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
11681  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
11682  break;
11683 
11684  default:
11685  SCIPerrorMessage("invalid comparison result\n");
11686  var = NULL;
11687  val0 = 0.0;
11688  val1 = 0.0;
11689  SCIPABORT();
11690  }
11691  assert(var != NULL);
11692 
11693  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
11694  if( SCIPisGT(scip, val0, val1) )
11695  {
11696  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
11697  {
11698  cons0dominatesrhs = FALSE;
11699  cons1dominateslhs = FALSE;
11700  }
11701  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
11702  {
11703  cons0dominateslhs = FALSE;
11704  cons1dominatesrhs = FALSE;
11705  }
11706  }
11707  else if( SCIPisLT(scip, val0, val1) )
11708  {
11709  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
11710  {
11711  cons0dominateslhs = FALSE;
11712  cons1dominatesrhs = FALSE;
11713  }
11714  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
11715  {
11716  cons0dominatesrhs = FALSE;
11717  cons1dominateslhs = FALSE;
11718  }
11719  }
11720  }
11721 
11722  /* check for disaggregated ranged rows */
11723  if( coefsequal || coefsnegated )
11724  {
11725  SCIP_CONS* consstay;
11726  SCIP_CONS* consdel;
11727 #ifndef NDEBUG
11728  SCIP_CONSDATA* consdatastay;
11729 #endif
11730  SCIP_CONSDATA* consdatadel;
11731  SCIP_Real lhs;
11732  SCIP_Real rhs;
11733  int consinddel;
11734 
11735  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
11736  * best left and right hand sides; delete the old constraints afterwards
11737  */
11738  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
11739  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
11740  SCIPdebugPrintCons(scip, cons0, NULL);
11741  SCIPdebugPrintCons(scip, cons1, NULL);
11742 
11743  if( coefsequal )
11744  {
11745  /* the coefficients of both rows are equal */
11746  lhs = MAX(consdata0->lhs, consdata1->lhs);
11747  rhs = MIN(consdata0->rhs, consdata1->rhs);
11748  }
11749  else
11750  {
11751  /* the coefficients of both rows are negations */
11752  lhs = MAX(consdata0->lhs, -consdata1->rhs);
11753  rhs = MIN(consdata0->rhs, -consdata1->lhs);
11754  }
11755  if( SCIPisFeasLT(scip, rhs, lhs) )
11756  {
11757  SCIPdebugMessage("aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
11758  *cutoff = TRUE;
11759  break;
11760  }
11761 
11762  /* check which constraint has to stay;
11763  * changes applied to an upgraded constraint will not be considered in the instance */
11764  if( consdata0->upgraded )
11765  {
11766  assert(!consdata1->upgraded);
11767  consstay = cons1;
11768 #ifndef NDEBUG
11769  consdatastay = consdata1;
11770 #endif
11771 
11772  consdel = cons0;
11773  consdatadel = consdata0;
11774  consinddel = chkind;
11775  }
11776  else
11777  {
11778  consstay = cons0;
11779 #ifndef NDEBUG
11780  consdatastay = consdata0;
11781 #endif
11782 
11783  consdel = cons1;
11784  consdatadel = consdata1;
11785  consinddel = c;
11786  }
11787 
11788  /* update the sides of consstay */
11789  SCIP_CALL( chgLhs(scip, consstay, lhs) );
11790  SCIP_CALL( chgRhs(scip, consstay, rhs) );
11791  if( !consdata0->upgraded )
11792  {
11793  assert(consstay == cons0);
11794  cons0lhs = consdata0->lhs;
11795  cons0rhs = consdata0->rhs;
11796  }
11797 
11798  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11799  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
11800 
11801  assert( !consdatastay->upgraded );
11802  /* delete consdel */
11803  SCIP_CALL( SCIPdelCons(scip, consdel) );
11804  conss[consinddel] = NULL;
11805  if( !consdatadel->upgraded )
11806  (*ndelconss)++;
11807  continue;
11808  }
11809 
11810  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
11811  * redundant
11812  */
11813  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
11814  {
11815  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
11816  SCIPdebugMessage("left hand side of linear constraint <%s> is dominated by <%s>:\n",
11817  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11818  SCIPdebugPrintCons(scip, cons0, NULL);
11819  SCIPdebugPrintCons(scip, cons1, NULL);
11820 
11821  /* check for infeasibility */
11822  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
11823  {
11824  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11825  *cutoff = TRUE;
11826  break;
11827  }
11828 
11829  /* remove redundant left hand side */
11830  if( !SCIPisInfinity(scip, -consdata0->lhs) )
11831  {
11832  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
11833  cons0lhs = consdata0->lhs;
11834  cons0isequality = FALSE;
11835  if( !consdata0->upgraded )
11836  {
11837  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11838  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11839 
11840  (*nchgsides)++;
11841  }
11842  }
11843  }
11844  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
11845  {
11846  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
11847  SCIPdebugMessage("left hand side of linear constraint <%s> is dominated by <%s>:\n",
11848  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
11849  SCIPdebugPrintCons(scip, cons1, NULL);
11850  SCIPdebugPrintCons(scip, cons0, NULL);
11851 
11852  /* check for infeasibility */
11853  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
11854  {
11855  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11856  *cutoff = TRUE;
11857  break;
11858  }
11859 
11860  /* remove redundant left hand side */
11861  if( !SCIPisInfinity(scip, -consdata1->lhs) )
11862  {
11863  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
11864  cons1isequality = FALSE;
11865  if( !consdata1->upgraded )
11866  {
11867  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11868  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11869 
11870  (*nchgsides)++;
11871  }
11872  }
11873  }
11874  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
11875  {
11876  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
11877  SCIPdebugMessage("right hand side of linear constraint <%s> is dominated by <%s>:\n",
11878  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11879  SCIPdebugPrintCons(scip, cons0, NULL);
11880  SCIPdebugPrintCons(scip, cons1, NULL);
11881 
11882  /* check for infeasibility */
11883  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
11884  {
11885  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11886  *cutoff = TRUE;
11887  break;
11888  }
11889 
11890  /* remove redundant right hand side */
11891  if( !SCIPisInfinity(scip, consdata0->rhs) )
11892  {
11893  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
11894  cons0rhs = consdata0->rhs;
11895  cons0isequality = FALSE;
11896  if( !consdata0->upgraded )
11897  {
11898  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11899  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11900 
11901  (*nchgsides)++;
11902  }
11903  }
11904  }
11905  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
11906  {
11907  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
11908  SCIPdebugMessage("right hand side of linear constraint <%s> is dominated by <%s>:\n",
11909  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
11910  SCIPdebugPrintCons(scip, cons1, NULL);
11911  SCIPdebugPrintCons(scip, cons0, NULL);
11912 
11913  /* check for infeasibility */
11914  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
11915  {
11916  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11917  *cutoff = TRUE;
11918  break;
11919  }
11920 
11921  /* remove redundant right hand side */
11922  if( !SCIPisInfinity(scip, consdata1->rhs) )
11923  {
11924  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
11925  cons1isequality = FALSE;
11926  if( !consdata1->upgraded )
11927  {
11928  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11929  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11930 
11931  (*nchgsides)++;
11932  }
11933  }
11934  }
11935 
11936  /* check for now redundant constraints */
11937  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
11938  {
11939  /* consdata0 became redundant */
11940  SCIPdebugMessage("linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
11941  SCIP_CALL( SCIPdelCons(scip, cons0) );
11942  conss[chkind] = NULL;
11943  if( !consdata0->upgraded )
11944  {
11945  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11946  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11947 
11948  (*ndelconss)++;
11949  }
11950  continue;
11951  }
11952  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
11953  {
11954  /* consdata1 became redundant */
11955  SCIPdebugMessage("linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
11956  SCIP_CALL( SCIPdelCons(scip, cons1) );
11957  conss[c] = NULL;
11958  if( !consdata1->upgraded )
11959  {
11960  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11961  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11962 
11963  (*ndelconss)++;
11964  }
11965  continue;
11966  }
11967 
11968  /* check, if we want to aggregate an (in)equality with an equality:
11969  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
11970  */
11971  if( tryaggregation )
11972  {
11973  SCIP_Bool aggregated;
11974 
11975  assert(consdata0->nvars == nvarscommon + nvars0minus1);
11976  assert(consdata1->nvars == nvarscommon + nvars1minus0);
11977 
11978  aggregated = FALSE;
11979  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
11980  {
11981  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
11982  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
11983  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
11984  nchgcoefs, &aggregated) );
11985 
11986  /* update array of active constraints */
11987  if( aggregated )
11988  {
11989  assert(!SCIPconsIsActive(cons0));
11990  assert(SCIPconsIsActive(cons1));
11991  conss[chkind] = NULL;
11992  }
11993  }
11994  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
11995  {
11996  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
11997  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
11998  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
11999  nchgcoefs, &aggregated) );
12000 
12001  /* update array of active constraints */
12002  if( aggregated )
12003  {
12004  assert(!SCIPconsIsActive(cons1));
12005  assert(SCIPconsIsActive(cons0));
12006  conss[c] = NULL;
12007  }
12008  }
12009  }
12010  }
12011 
12012  /* free temporary memory */
12013  SCIPfreeBufferArray(scip, &diffidx1minus0);
12014  SCIPfreeBufferArray(scip, &diffidx0minus1);
12015  SCIPfreeBufferArray(scip, &commonidx1);
12016  SCIPfreeBufferArray(scip, &commonidx0);
12017 
12018  return SCIP_OKAY;
12019 }
12020 
12021 /** applies full dual presolving on variables that only appear in linear constraints */
12022 static
12024  SCIP* scip, /**< SCIP data structure */
12025  SCIP_CONS** conss, /**< constraint set */
12026  int nconss, /**< number of constraints */
12027  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
12028  int* nchgbds /**< pointer to count the number of bound changes */
12029  )
12030 {
12031  SCIP_Real* redlb;
12032  SCIP_Real* redub;
12033  int* nlocksdown;
12034  int* nlocksup;
12035  SCIP_Bool* isimplint;
12036  SCIP_VAR** origvars;
12037  SCIP_VAR** vars;
12038  SCIP_VAR** conscontvars;
12039  int nvars;
12040  int nbinvars;
12041  int nintvars;
12042  int ncontvars;
12043  int v;
12044  int c;
12045 
12046  /* we calculate redundancy bounds with the following meaning:
12047  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
12048  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
12049  * then:
12050  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
12051  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
12052  */
12053 
12054  /* Additionally, we detect continuous variables that are implicitly integral.
12055  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
12056  * and all constraints (including the bounds as trivial constraints) in which:
12057  * c_j > 0: the variable is down-locked,
12058  * c_j < 0: the variable is up-locked,
12059  * c_j = 0: the variable appears
12060  * have, apart from j, only integer variables with integral coefficients and integral sides.
12061  * This is because then, the value of the variable is either determined by one of its bounds or
12062  * by one of these constraints, and in all cases, the value of the variable is integral.
12063  */
12064 
12065  assert(scip != NULL);
12066  assert(nconss == 0 || conss != NULL);
12067  assert(nchgbds != NULL);
12068  assert(!SCIPinProbing(scip));
12069 
12070  /* get active variables */
12071  nvars = SCIPgetNVars(scip);
12072  origvars = SCIPgetVars(scip);
12073 
12074  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
12075  nbinvars = SCIPgetNBinVars(scip);
12076  if( nbinvars == nvars )
12077  return SCIP_OKAY;
12078 
12079  /* get number of continuous variables */
12080  ncontvars = SCIPgetNContVars(scip);
12081  nintvars = nvars - ncontvars;
12082 
12083  /* copy the variable array since this array might change during the curse of this algorithm */
12084  nvars = nvars - nbinvars;
12085  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
12086 
12087  /* allocate temporary memory */
12088  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
12089  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
12090  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
12091  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
12092  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
12093  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
12094 
12095  /* initialize redundancy bounds */
12096  for( v = 0; v < nvars; ++v )
12097  {
12098  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
12099  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
12100  redub[v] = SCIPvarGetUbGlobal(vars[v]);
12101  }
12102  BMSclearMemoryArray(nlocksdown, nvars);
12103  BMSclearMemoryArray(nlocksup, nvars);
12104 
12105  /* Initialize isimplint array: variable may be implied integer if both bounds are integral.
12106  * We better not use SCIPisFeasIntegral() in these checks.
12107  */
12108  for( v = 0; v < ncontvars; v++ )
12109  {
12110  SCIP_VAR* var;
12111  SCIP_Real lb;
12112  SCIP_Real ub;
12113 
12114  var = vars[v + nintvars - nbinvars];
12115  lb = SCIPvarGetLbGlobal(var);
12116  ub = SCIPvarGetUbGlobal(var);
12117  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb))
12118  && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
12119  }
12120 
12121  /* scan all constraints */
12122  for( c = 0; c < nconss; ++c )
12123  {
12124  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
12125  * part of checked disjunctions)
12126  */
12127  if( SCIPconsIsLocked(conss[c]) )
12128  {
12129  SCIP_CONSDATA* consdata;
12130  SCIP_Bool lhsexists;
12131  SCIP_Bool rhsexists;
12132  SCIP_Bool hasimpliedpotential;
12133  SCIP_Bool integralcoefs;
12134  int nlockspos;
12135  int contvarpos;
12136  int nconscontvars;
12137  int i;
12138 
12139  consdata = SCIPconsGetData(conss[c]);
12140  assert(consdata != NULL);
12141 
12142  /* get number of times the constraint was locked */
12143  nlockspos = SCIPconsGetNLocksPos(conss[c]);
12144 
12145  /* we do not want to include constraints with locked negation (this would be too weird) */
12146  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
12147  {
12148  /* mark all continuous variables as not being implicit integral */
12149  for( i = 0; i < consdata->nvars; ++i )
12150  {
12151  SCIP_VAR* var;
12152 
12153  var = consdata->vars[i];
12155  {
12156  int contv;
12157  contv = SCIPvarGetProbindex(var) - nintvars;
12158  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
12159  isimplint[contv] = FALSE;
12160  }
12161  }
12162  continue;
12163  }
12164 
12165  /* check for existing sides */
12166  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
12167  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
12168 
12169  /* count locks and update redundancy bounds */
12170  contvarpos = -1;
12171  nconscontvars = 0;
12172  hasimpliedpotential = FALSE;
12173  integralcoefs = !SCIPconsIsModifiable(conss[c]);
12174 
12175  for( i = 0; i < consdata->nvars; ++i )
12176  {
12177  SCIP_VAR* var;
12178  SCIP_Real val;
12179  SCIP_Real minresactivity;
12180  SCIP_Real maxresactivity;
12181  SCIP_Real newredlb;
12182  SCIP_Real newredub;
12183  SCIP_Bool minisrelax;
12184  SCIP_Bool maxisrelax;
12185  SCIP_Bool isminsettoinfinity;
12186  SCIP_Bool ismaxsettoinfinity;
12187  int arrayindex;
12188 
12189  var = consdata->vars[i];
12190  val = consdata->vals[i];
12191 
12192  /* check if still all integer variables have integral coefficients */
12193  if( SCIPvarIsIntegral(var) )
12194  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
12195 
12196  /* we do not need to process binary variables */
12197  if( SCIPvarIsBinary(var) )
12198  continue;
12199 
12200  if( SCIPconsIsModifiable(conss[c]) )
12201  {
12202  minresactivity = -SCIPinfinity(scip);
12203  maxresactivity = SCIPinfinity(scip);
12204  isminsettoinfinity = TRUE;
12205  ismaxsettoinfinity = TRUE;
12206  }
12207  else
12208  {
12209  /* calculate residual activity bounds if variable would be fixed to zero */
12210  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
12211  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
12212 
12213  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
12214  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
12215  * This is needed, because we do not want to rely on relaxed finite resactivities.
12216  */
12217  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
12218 
12219  /* check minresactivity for reliability */
12220  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
12221  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
12222 
12223  /* check maxresactivity for reliability */
12224  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
12225  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
12226  }
12227 
12228  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
12229 
12230  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
12231 
12232  newredlb = redlb[arrayindex];
12233  newredub = redub[arrayindex];
12234  if( val > 0.0 )
12235  {
12236  if( lhsexists )
12237  {
12238  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
12239  nlocksdown[arrayindex] += nlockspos;
12240  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
12241  }
12242  if( rhsexists )
12243  {
12244  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
12245  nlocksup[arrayindex] += nlockspos;
12246  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
12247  }
12248  }
12249  else
12250  {
12251  if( lhsexists )
12252  {
12253  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
12254  nlocksup[arrayindex] += nlockspos;
12255  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
12256  }
12257  if( rhsexists )
12258  {
12259  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
12260  nlocksdown[arrayindex] += nlockspos;
12261  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
12262  }
12263  }
12264 
12265  /* if the variable is integer, we have to round the value to the next integral value */
12266  if( SCIPvarIsIntegral(var) )
12267  {
12268  if( !SCIPisInfinity(scip, newredlb) )
12269  newredlb = SCIPceil(scip, newredlb);
12270  if( !SCIPisInfinity(scip, -newredub) )
12271  newredub = SCIPfloor(scip, newredub);
12272  }
12273 
12274  /* update redundancy bounds */
12275  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
12276  redub[arrayindex] = MIN(redub[arrayindex], newredub);
12277 
12278  /* collect the continuous variables of the constraint */
12280  {
12281  int contv;
12282 
12283  assert(nconscontvars < ncontvars);
12284  contvarpos = i;
12285  conscontvars[nconscontvars] = var;
12286  nconscontvars++;
12287 
12288  contv = SCIPvarGetProbindex(var) - nintvars;
12289  assert(0 <= contv && contv < ncontvars);
12290  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
12291  }
12292  }
12293 
12294  /* update implied integer status of continuous variables */
12295  if( hasimpliedpotential )
12296  {
12297  if( nconscontvars > 1 || !integralcoefs )
12298  {
12299  /* there is more than one continuous variable or the integer variables have fractional coefficients:
12300  * none of the continuous variables is implied integer
12301  */
12302  for( i = 0; i < nconscontvars; i++ )
12303  {
12304  int contv;
12305  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
12306  assert(0 <= contv && contv < ncontvars);
12307  isimplint[contv] = FALSE;
12308  }
12309  }
12310  else
12311  {
12312  SCIP_VAR* var;
12313  SCIP_Real val;
12314  SCIP_Real absval;
12315  int contv;
12316 
12317  /* there is exactly one continuous variable and the integer variables have integral coefficients:
12318  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
12319  * side(s) of the constraint is integral
12320  */
12321  assert(nconscontvars == 1);
12322  assert(0 <= contvarpos && contvarpos < consdata->nvars);
12323  var = consdata->vars[contvarpos];
12324  val = consdata->vals[contvarpos];
12325  contv = SCIPvarGetProbindex(var) - nintvars;
12326  assert(0 <= contv && contv < ncontvars);
12327  assert(isimplint[contv]);
12328 
12329  absval = REALABS(val);
12330  if( !SCIPisEQ(scip, absval, 1.0) )
12331  isimplint[contv] = FALSE;
12332  else
12333  {
12334  SCIP_Real obj;
12335 
12336  obj = SCIPvarGetObj(var);
12337  if( obj * val >= 0.0 && lhsexists )
12338  {
12339  /* the variable may be blocked by the constraint's left hand side */
12340  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
12341  }
12342  if( obj * val <= 0.0 && rhsexists )
12343  {
12344  /* the variable may be blocked by the constraint's left hand side */
12345  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
12346  }
12347  }
12348  }
12349  }
12350  }
12351  }
12352 
12353  /* check if any bounds can be tightened due to optimality */
12354  for( v = 0; v < nvars; ++v )
12355  {
12356  SCIP_VAR* var;
12357  SCIP_Real obj;
12358  SCIP_Bool infeasible;
12359  SCIP_Bool tightened;
12360 
12361  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
12362  assert(SCIPvarGetNLocksDown(vars[v]) >= nlocksdown[v]);
12363  assert(SCIPvarGetNLocksUp(vars[v]) >= nlocksup[v]);
12364 
12365  var = vars[v];
12366  obj = SCIPvarGetObj(var);
12367  if( obj >= 0.0 )
12368  {
12369  /* making the variable as small as possible does not increase the objective:
12370  * check if all down locks of the variables are due to linear constraints;
12371  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
12372  */
12373  if( SCIPvarGetNLocksDown(var) == nlocksdown[v]
12374  && !SCIPisInfinity(scip, -redlb[v])
12375  && redlb[v] < SCIPvarGetUbGlobal(var) )
12376  {
12377  SCIP_Real ub;
12378 
12379  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
12380  * -> tighten upper bound to x_v <= redlb[v]
12381  */
12382  SCIPdebugMessage("variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
12384  redlb[v]);
12385  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
12386  assert(!infeasible);
12387 
12388  ub = SCIPvarGetUbGlobal(var);
12389  redub[v] = MIN(redub[v], ub);
12390  if( tightened )
12391  (*nchgbds)++;
12392  }
12393  }
12394  if( obj <= 0.0 )
12395  {
12396  /* making the variable as large as possible does not increase the objective:
12397  * check if all up locks of the variables are due to linear constraints;
12398  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
12399  */
12400  if( SCIPvarGetNLocksUp(var) == nlocksup[v]
12401  && !SCIPisInfinity(scip, redub[v])
12402  && redub[v] > SCIPvarGetLbGlobal(var) )
12403  {
12404  SCIP_Real lb;
12405 
12406  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
12407  * -> tighten lower bound to x_v >= redub[v]
12408  */
12409  SCIPdebugMessage("variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
12411  redub[v]);
12412  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
12413  assert(!infeasible);
12414 
12415  lb = SCIPvarGetLbGlobal(var);
12416  redlb[v] = MAX(redlb[v], lb);
12417  if( tightened )
12418  (*nchgbds)++;
12419  }
12420  }
12421  }
12422 
12423  /* upgrade continuous variables to implied integers */
12424  for( v = nintvars - nbinvars; v < nvars; ++v )
12425  {
12426  SCIP_VAR* var;
12427  SCIP_Bool infeasible;
12428 
12429  var = vars[v];
12430  assert(var != NULL);
12431 
12432  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
12433  assert(SCIPvarGetNLocksDown(var) >= nlocksdown[v]);
12434  assert(SCIPvarGetNLocksUp(var) >= nlocksup[v]);
12435  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
12436 
12437  /* we can only conclude implied integrality if the variable appears in no other constraint */
12438  if( isimplint[v - nintvars + nbinvars]
12439  && SCIPvarGetNLocksDown(var) == nlocksdown[v]
12440  && SCIPvarGetNLocksUp(var) == nlocksup[v] )
12441  {
12442 
12443  /* since we locally copied the variable array we can change the variable type immediately */
12444  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
12445 
12446  if( infeasible )
12447  {
12448  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
12449  *cutoff = TRUE;
12450 
12451  break;
12452  }
12453 
12454  SCIPdebugMessage("dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
12456  }
12457  }
12458 
12459  /* free temporary memory */
12460  SCIPfreeBufferArray(scip, &conscontvars);
12461  SCIPfreeBufferArray(scip, &isimplint);
12462  SCIPfreeBufferArray(scip, &nlocksup);
12463  SCIPfreeBufferArray(scip, &nlocksdown);
12464  SCIPfreeBufferArray(scip, &redub);
12465  SCIPfreeBufferArray(scip, &redlb);
12466 
12467  SCIPfreeBufferArray(scip, &vars);
12468 
12469  return SCIP_OKAY;
12470 }
12471 
12472 
12473 /*
12474  * Callback methods of constraint handler
12475  */
12476 
12477 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
12478 static
12479 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
12480 { /*lint --e{715}*/
12481  assert(scip != NULL);
12482  assert(conshdlr != NULL);
12483  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12484 
12485  /* call inclusion method of constraint handler */
12487 
12488  *valid = TRUE;
12489 
12490  return SCIP_OKAY;
12491 }
12492 
12493 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
12494 static
12495 SCIP_DECL_CONSFREE(consFreeLinear)
12496 { /*lint --e{715}*/
12497  SCIP_CONSHDLRDATA* conshdlrdata;
12498 
12499  assert(scip != NULL);
12500  assert(conshdlr != NULL);
12501  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12502 
12503  /* free constraint handler data */
12504  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12505  assert(conshdlrdata != NULL);
12506 
12507  conshdlrdataFree(scip, &conshdlrdata);
12508 
12510 
12511  return SCIP_OKAY;
12512 }
12513 
12514 
12515 /** initialization method of constraint handler (called after problem was transformed) */
12516 static
12517 SCIP_DECL_CONSINIT(consInitLinear)
12518 {
12519  SCIP_CONSHDLRDATA* conshdlrdata;
12520  int c;
12521 
12522  assert(scip != NULL);
12523 
12524  /* get event handler */
12525  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12526  assert(conshdlrdata != NULL);
12527  assert(conshdlrdata->eventhdlr != NULL);
12528  assert(nconss == 0 || conss != NULL);
12529 
12530  /* catch events for the constraints */
12531  for( c = 0; c < nconss; ++c )
12532  {
12533  /* catch all events */
12534  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
12535  }
12536 
12537  return SCIP_OKAY;
12538 }
12539 
12540 
12541 /** deinitialization method of constraint handler (called before transformed problem is freed) */
12542 static
12543 SCIP_DECL_CONSEXIT(consExitLinear)
12544 {
12545  SCIP_CONSHDLRDATA* conshdlrdata;
12546  int c;
12547 
12548  assert(scip != NULL);
12549 
12550  /* get event handler */
12551  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12552  assert(conshdlrdata != NULL);
12553  assert(conshdlrdata->eventhdlr != NULL);
12554 
12555  /* drop events for the constraints */
12556  for( c = nconss - 1; c >= 0; --c )
12557  {
12558  SCIP_CONSDATA* consdata;
12559 
12560  consdata = SCIPconsGetData(conss[c]);
12561  assert(consdata != NULL);
12562 
12563  if( consdata->eventdata != NULL )
12564  {
12565  /* drop all events */
12566  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
12567  assert(consdata->eventdata == NULL);
12568  }
12569  }
12570 
12571  return SCIP_OKAY;
12572 
12573 }
12574 
12575 #ifdef WITH_PRINTORIGCONSTYPES
12576 
12577 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
12578 static
12579 SCIP_Bool isRangedRow(
12580  SCIP* scip, /**< SCIP data structure */
12581  SCIP_CONS* cons /**< constraint */
12582  )
12583 {
12584  assert(scip != NULL);
12585  assert(cons != NULL);
12586  assert(SCIPconsGetData(cons) != NULL);
12587 
12588  return !(SCIPisEQ(scip, SCIPconsGetData(cons)->lhs, SCIPconsGetData(cons)->rhs)
12589  || SCIPisInfinity(scip, -SCIPconsGetData(cons)->lhs) || SCIPisInfinity(scip, SCIPconsGetData(cons)->rhs) );
12590 }
12591 
12592 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
12593 static
12594 SCIP_Bool isFiniteNonnegativeIntegral(
12595  SCIP* scip, /**< SCIP data structure */
12596  SCIP_Real x /**< value */
12597  )
12598 {
12599  assert(scip != NULL);
12600 
12601  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
12602 }
12603 
12604 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
12605 static
12606 SCIP_DECL_CONSINITPRE(consInitpreLinear)
12607 { /*lint --e{715}*/
12608  int counter[(int)SCIP_CONSTYPE_GENERAL + 1];
12609  int c;
12610 
12611  assert(scip != NULL);
12612 
12613  /* initialize counter for constraint types to zero */
12614  BMSclearMemoryArray(counter, (int)SCIP_CONSTYPE_GENERAL + 1);
12615 
12616  /* loop through all constraints */
12617  for( c = 0; c < nconss; c++ )
12618  {
12619  SCIP_CONS* cons;
12620  SCIP_CONSDATA* consdata;
12621  int i;
12622 
12623  /* get constraint */
12624  cons = conss[c];
12625  assert(cons != NULL);
12626 
12627  /* get constraint data */
12628  consdata = SCIPconsGetData(cons);
12629  assert(consdata != NULL);
12630 
12631  /* merge multiples and delete variables with zero coefficient */
12632  SCIP_CALL( mergeMultiples(scip, cons) );
12633  for( i = 0; i < consdata->nvars; i++ )
12634  {
12635  assert(!SCIPisZero(scip, consdata->vals[i]));
12636  }
12637 
12638  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
12639  if( consdata->nvars == 0 )
12640  {
12641  SCIPdebugMessage("classified as EMPTY: ");
12642  SCIPdebugPrintCons(scip, cons, NULL);
12643  counter[SCIP_CONSTYPE_EMPTY]++;
12644  continue;
12645  }
12646 
12647  /* is constraint of type SCIP_CONSTYPE_FREE? */
12648  if( SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, -consdata->lhs) )
12649  {
12650  SCIPdebugMessage("classified as FREE: ");
12651  SCIPdebugPrintCons(scip, cons, NULL);
12652  counter[SCIP_CONSTYPE_FREE]++;
12653  continue;
12654  }
12655 
12656  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
12657  if( consdata->nvars == 1 )
12658  {
12659  SCIPdebugMessage("classified as SINGLETON: ");
12660  SCIPdebugPrintCons(scip, cons, NULL);
12661  counter[SCIP_CONSTYPE_SINGLETON] += isRangedRow(scip, cons) ? 2 : 1;
12662  continue;
12663  }
12664 
12665  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
12666  if( consdata->nvars == 2 && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12667  {
12668  SCIPdebugMessage("classified as AGGREGATION: ");
12669  SCIPdebugPrintCons(scip, cons, NULL);
12670  counter[SCIP_CONSTYPE_AGGREGATION]++;
12671  continue;
12672  }
12673 
12674  /* is constraint of type SCIP_CONSTYPE_{VARBOUND}? */
12675  if( consdata->nvars == 2 )
12676  {
12677  SCIPdebugMessage("classified as VARBOUND: ");
12678  SCIPdebugPrintCons(scip, cons, NULL);
12679  counter[SCIP_CONSTYPE_VARBOUND] += isRangedRow(scip, cons) ? 2 : 1;
12680  continue;
12681  }
12682 
12683  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
12684  {
12685  SCIP_Real scale;
12686  SCIP_Real b;
12687  SCIP_Bool unmatched;
12688  int nnegbinvars;
12689 
12690  unmatched = FALSE;
12691  nnegbinvars = 0;
12692 
12693  scale = REALABS(consdata->vals[0]);
12694  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12695  {
12696  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12697  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
12698  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
12699  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
12700 
12701  if( consdata->vals[i] < 0.0 )
12702  nnegbinvars++;
12703  }
12704 
12705  if( !unmatched )
12706  {
12707  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12708  {
12709  b = consdata->rhs/scale + nnegbinvars;
12710  if( SCIPisEQ(scip, 1.0, b) )
12711  {
12712  SCIPdebugMessage("classified as SETPARTITION: ");
12713  SCIPdebugPrintCons(scip, cons, NULL);
12714  counter[SCIP_CONSTYPE_SETPARTITION]++;
12715  continue;
12716  }
12717  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
12718  {
12719  SCIPdebugMessage("classified as CARDINALITY: ");
12720  SCIPdebugPrintCons(scip, cons, NULL);
12721  counter[SCIP_CONSTYPE_CARDINALITY]++;
12722  continue;
12723  }
12724  }
12725 
12726  b = consdata->rhs/scale + nnegbinvars;
12727  if( SCIPisEQ(scip, 1.0, b) )
12728  {
12729  SCIPdebugMessage("classified as SETPACKING: ");
12730  SCIPdebugPrintCons(scip, cons, NULL);
12731  counter[SCIP_CONSTYPE_SETPACKING]++;
12732  consdata->rhs = SCIPinfinity(scip);
12733  }
12734  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
12735  {
12736  SCIPdebugMessage("classified as INVKNAPSACK: ");
12737  SCIPdebugPrintCons(scip, cons, NULL);
12738  counter[SCIP_CONSTYPE_INVKNAPSACK]++;
12739  consdata->rhs = SCIPinfinity(scip);
12740  }
12741 
12742  b = consdata->lhs/scale + nnegbinvars;
12743  if( SCIPisEQ(scip, 1.0, b) )
12744  {
12745  SCIPdebugMessage("classified as SETCOVERING: ");
12746  SCIPdebugPrintCons(scip, cons, NULL);
12747  counter[SCIP_CONSTYPE_SETCOVERING]++;
12748  consdata->lhs = -SCIPinfinity(scip);
12749  }
12750 
12751  if( SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
12752  continue;
12753  }
12754  }
12755 
12756  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
12757  /* @todo If coefficients or rhs are not integral, we currently do not check
12758  * if the constraint could be scaled (finitely), such that they are.
12759  */
12760  {
12761  SCIP_Real b;
12762  SCIP_Bool unmatched;
12763 
12764  b = consdata->rhs;
12765  unmatched = FALSE;
12766  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12767  {
12768  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12769  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
12770  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
12771  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
12772 
12773  if( SCIPisNegative(scip, consdata->vals[i]) )
12774  b -= consdata->vals[i];
12775  }
12776  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
12777 
12778  if( !unmatched )
12779  {
12780  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12781  {
12782  SCIPdebugMessage("classified as EQKNAPSACK: ");
12783  SCIPdebugPrintCons(scip, cons, NULL);
12784  counter[SCIP_CONSTYPE_EQKNAPSACK]++;
12785  continue;
12786  }
12787  else
12788  {
12789  SCIP_Bool matched;
12790 
12791  matched = FALSE;
12792  for( i = 0; i < consdata->nvars && !matched; i++ )
12793  {
12794  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
12795  }
12796 
12797  SCIPdebugMessage("classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
12798  SCIPdebugPrintCons(scip, cons, NULL);
12799  counter[matched ? SCIP_CONSTYPE_BINPACKING : SCIP_CONSTYPE_KNAPSACK]++;
12800  }
12801 
12802  if( SCIPisInfinity(scip, -consdata->lhs) )
12803  continue;
12804  else
12805  consdata->rhs = SCIPinfinity(scip);
12806  }
12807  }
12808 
12809  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
12810  {
12811  SCIP_Real b;
12812  SCIP_Bool unmatched;
12813 
12814  unmatched = FALSE;
12815 
12816  b = consdata->rhs;
12817  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
12818 
12819  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12820  {
12821  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12822  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
12823  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
12824  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
12825  }
12826 
12827  if( !unmatched )
12828  {
12829  SCIPdebugMessage("classified as INTKNAPSACK: ");
12830  SCIPdebugPrintCons(scip, cons, NULL);
12831  counter[SCIP_CONSTYPE_INTKNAPSACK]++;
12832 
12833  if( SCIPisInfinity(scip, -consdata->lhs) )
12834  continue;
12835  else
12836  consdata->rhs = SCIPinfinity(scip);
12837  }
12838  }
12839 
12840  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
12841  {
12842  SCIP_Bool unmatched;
12843 
12844  unmatched = FALSE;
12845  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12846  {
12847  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
12848  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
12849  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
12850  unmatched = TRUE;
12851  }
12852 
12853  if( !unmatched )
12854  {
12855  SCIPdebugMessage("classified as MIXEDBINARY (%d): ", isRangedRow(scip, cons) ? 2 : 1);
12856  SCIPdebugPrintCons(scip, cons, NULL);
12857  counter[SCIP_CONSTYPE_MIXEDBINARY] += isRangedRow(scip, cons) ? 2 : 1;
12858  continue;
12859  }
12860  }
12861 
12862  /* no special structure detected */
12863  SCIPdebugMessage("classified as GENERAL: ");
12864  SCIPdebugPrintCons(scip, cons, NULL);
12865  counter[SCIP_CONSTYPE_GENERAL] += isRangedRow(scip, cons) ? 2 : 1;
12866  }
12867 
12868  /* print statistics */
12869  SCIPinfoMessage(scip, NULL, "\n");
12870  SCIPinfoMessage(scip, NULL, "Number of constraints according to type:\n");
12871  SCIPinfoMessage(scip, NULL, "----------------------------------------\n");
12872  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EMPTY %6d\n", 0, counter[ 0]);
12873  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_FREE %6d\n", 1, counter[ 1]);
12874  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SINGLETON %6d\n", 2, counter[ 2]);
12875  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_AGGREGATION %6d\n", 3, counter[ 3]);
12876  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_VARBOUND %6d\n", 4, counter[ 4]);
12877  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPARTITION %6d\n", 5, counter[ 5]);
12878  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPACKING %6d\n", 6, counter[ 6]);
12879  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETCOVERING %6d\n", 7, counter[ 7]);
12880  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_CARDINALITY %6d\n", 8, counter[ 8]);
12881  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INVKNAPSACK %6d\n", 9, counter[ 9]);
12882  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EQKNAPSACK %6d\n", 10, counter[10]);
12883  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_BINPACKING %6d\n", 11, counter[11]);
12884  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_KNAPSACK %6d\n", 12, counter[12]);
12885  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INTKNAPSACK %6d\n", 13, counter[13]);
12886  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_MIXEDBINARY %6d\n", 14, counter[14]);
12887  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_GENERAL %6d\n", 15, counter[15]);
12888  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
12889 
12890  SCIPinfoMessage(scip, NULL, " EMPTY");
12891  SCIPinfoMessage(scip, NULL, " FREE");
12892  SCIPinfoMessage(scip, NULL, " SING");
12893  SCIPinfoMessage(scip, NULL, " AGGR");
12894  SCIPinfoMessage(scip, NULL, " VARBD");
12895  SCIPinfoMessage(scip, NULL, " SETPART");
12896  SCIPinfoMessage(scip, NULL, " SETPACK");
12897  SCIPinfoMessage(scip, NULL, " SETCOV");
12898  SCIPinfoMessage(scip, NULL, " CARD");
12899  SCIPinfoMessage(scip, NULL, " INVKNAP");
12900  SCIPinfoMessage(scip, NULL, " EQKNAP");
12901  SCIPinfoMessage(scip, NULL, " BINPACK");
12902  SCIPinfoMessage(scip, NULL, " KNAP");
12903  SCIPinfoMessage(scip, NULL, " INTKNAP");
12904  SCIPinfoMessage(scip, NULL, " MIXBIN");
12905  SCIPinfoMessage(scip, NULL, " GEN\n");
12906  for( c = 0; c <= (int)SCIP_CONSTYPE_GENERAL; c++ )
12907  {
12908  SCIPinfoMessage(scip, NULL, "%9d", counter[c]);
12909  }
12910 
12911  SCIPinfoMessage(scip, NULL, "\n\n");
12912  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
12913 
12914  return SCIP_OKAY;
12915 }
12916 #endif
12917 
12918 
12919 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
12920 static
12921 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
12922 { /*lint --e{715}*/
12923  int c;
12924 #ifdef SCIP_STATISTIC
12925  int ngoodconss;
12926  int nallconss;
12927 #endif
12928 
12929  /* delete all linear constraints that were upgraded to a more specific constraint type;
12930  * make sure, only active variables remain in the remaining constraints
12931  */
12932  assert(scip != NULL);
12933 
12934 #ifdef SCIP_STATISTIC
12935  /* count number of well behaved linear constraints */
12936 
12937  ngoodconss = 0;
12938  nallconss = 0;
12939 
12940  for( c = 0; c < nconss; ++c )
12941  {
12942  SCIP_CONSDATA* consdata;
12943 
12944  if( SCIPconsIsDeleted(conss[c]) )
12945  continue;
12946 
12947  consdata = SCIPconsGetData(conss[c]);
12948  assert(consdata != NULL);
12949 
12950  if( consdata->upgraded )
12951  continue;
12952 
12953  nallconss++;
12954 
12955  consdataRecomputeMaxActivityDelta(scip, consdata);
12956 
12957  if( SCIPisLT(scip, consdata->maxactdelta, MAXACTIVITYDELTATHR) )
12958  ngoodconss++;
12959  }
12960  if( nallconss )
12961  {
12962  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
12963  }
12964 #endif
12965 
12966  for( c = 0; c < nconss; ++c )
12967  {
12968  SCIP_CONSDATA* consdata;
12969 
12970  if( SCIPconsIsDeleted(conss[c]) )
12971  continue;
12972 
12973  consdata = SCIPconsGetData(conss[c]);
12974  assert(consdata != NULL);
12975 
12976  if( consdata->upgraded )
12977  {
12978  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
12979  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
12980  */
12981  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
12982  }
12983  else
12984  {
12985  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
12986  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
12987  }
12988  }
12989 
12990  return SCIP_OKAY;
12991 }
12992 
12993 
12994 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
12995 static
12996 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
12997 { /*lint --e{715}*/
12998  int c;
12999 
13000  assert(scip != NULL);
13001 
13002  /* release the rows of all constraints */
13003  for( c = 0; c < nconss; ++c )
13004  {
13005  SCIP_CONSDATA* consdata;
13006 
13007  consdata = SCIPconsGetData(conss[c]);
13008  assert(consdata != NULL);
13009 
13010  if( consdata->row != NULL )
13011  {
13012  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
13013  }
13014  }
13015 
13016  /* if this is a restart, convert cutpool rows into linear constraints */
13017  if( restart )
13018  {
13019  int ncutsadded;
13020 
13021  ncutsadded = 0;
13022 
13023  /* create out of all active cuts in cutpool linear constraints */
13024  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
13025 
13026  if( ncutsadded > 0 )
13027  {
13029  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
13030  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
13031  * line correctly
13032  */
13034  }
13035  }
13036 
13037  return SCIP_OKAY;
13038 }
13039 
13040 
13041 /** frees specific constraint data */
13042 static
13043 SCIP_DECL_CONSDELETE(consDeleteLinear)
13044 { /*lint --e{715}*/
13045  SCIP_CONSHDLRDATA* conshdlrdata;
13046 
13047  assert(scip != NULL);
13048  assert(conshdlr != NULL);
13049  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13050 
13051  /* get event handler */
13052  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13053  assert(conshdlrdata != NULL);
13054  assert(conshdlrdata->eventhdlr != NULL);
13055 
13056  /* free event datas */
13057  if( (*consdata)->eventdata != NULL )
13058  {
13059  /* drop bound change events of variables */
13060  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
13061  }
13062  assert((*consdata)->eventdata == NULL);
13063 
13064  /* free linear constraint */
13065  SCIP_CALL( consdataFree(scip, consdata) );
13066 
13067  return SCIP_OKAY;
13068 }
13069 
13070 
13071 /** transforms constraint data into data belonging to the transformed problem */
13072 static
13073 SCIP_DECL_CONSTRANS(consTransLinear)
13074 { /*lint --e{715}*/
13075  SCIP_CONSHDLRDATA* conshdlrdata;
13076  SCIP_CONSDATA* sourcedata;
13077  SCIP_CONSDATA* targetdata;
13078 
13079  /*debugMessage("Trans method of linear constraints\n");*/
13080 
13081  assert(scip != NULL);
13082  assert(conshdlr != NULL);
13083  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13084  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
13085  assert(sourcecons != NULL);
13086  assert(targetcons != NULL);
13088  sourcedata = SCIPconsGetData(sourcecons);
13089  assert(sourcedata != NULL);
13090  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
13091 
13092  /* get event handler */
13093  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13094  assert(conshdlrdata != NULL);
13095  assert(conshdlrdata->eventhdlr != NULL);
13096 
13097  /* create linear constraint data for target constraint */
13098  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
13099 
13100  /* create target constraint */
13101  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
13102  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
13103  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
13104  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
13105  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
13106 
13107  if( SCIPisTransformed(scip) && needEvents(scip) )
13108  {
13109  /* catch bound change events of variables */
13110  SCIP_CALL( consCatchAllEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
13111  assert(targetdata->eventdata != NULL);
13112  }
13113 
13114  return SCIP_OKAY;
13115 }
13116 
13117 
13118 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
13119 static
13120 SCIP_DECL_CONSINITLP(consInitlpLinear)
13121 { /*lint --e{715}*/
13122  SCIP_Bool cutoff;
13123  int c;
13124 
13125  assert(scip != NULL);
13126  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13127 
13128  for( c = 0; c < nconss; ++c )
13129  {
13130  assert(SCIPconsIsInitial(conss[c]));
13131  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
13132  /* cannot use cutoff here, since initlp has no return value */
13133  }
13135  return SCIP_OKAY;
13136 }
13137 
13138 
13139 /** separation method of constraint handler for LP solutions */
13140 static
13141 SCIP_DECL_CONSSEPALP(consSepalpLinear)
13142 { /*lint --e{715}*/
13143  SCIP_CONSHDLRDATA* conshdlrdata;
13144  SCIP_Real loclowerbound;
13145  SCIP_Real glblowerbound;
13146  SCIP_Real cutoffbound;
13147  SCIP_Real maxbound;
13148  SCIP_Bool separatecards;
13149  SCIP_Bool cutoff;
13150  int c;
13151  int depth;
13152  int nrounds;
13153  int maxsepacuts;
13154  int ncuts;
13156  assert(scip != NULL);
13157  assert(conshdlr != NULL);
13158  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13159  assert(result != NULL);
13160 
13161  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13162  assert(conshdlrdata != NULL);
13163  depth = SCIPgetDepth(scip);
13164  nrounds = SCIPgetNSepaRounds(scip);
13165 
13166  /*debugMessage("Sepa method of linear constraints\n");*/
13167 
13168  *result = SCIP_DIDNOTRUN;
13169 
13170  /* only call the separator a given number of times at each node */
13171  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
13172  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
13173  return SCIP_OKAY;
13174 
13175  /* get the maximal number of cuts allowed in a separation round */
13176  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
13177 
13178  /* check if we want to produce knapsack cardinality cuts at this node */
13179  loclowerbound = SCIPgetLocalLowerbound(scip);
13180  glblowerbound = SCIPgetLowerbound(scip);
13181  cutoffbound = SCIPgetCutoffbound(scip);
13182  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
13183  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
13184  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
13185 
13186  *result = SCIP_DIDNOTFIND;
13187  ncuts = 0;
13188  cutoff = FALSE;
13189 
13190  /* check all useful linear constraints for feasibility */
13191  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
13192  {
13193  /*debugMessage("separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
13194  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
13195  }
13196 
13197  /* adjust return value */
13198  if( cutoff )
13199  *result = SCIP_CUTOFF;
13200  else if( ncuts > 0 )
13201  *result = SCIP_SEPARATED;
13202 
13203  /* combine linear constraints to get more cuts */
13204  /**@todo further cuts of linear constraints */
13205 
13206  return SCIP_OKAY;
13207 }
13208 
13209 
13210 /** separation method of constraint handler for arbitrary primal solutions */
13211 static
13212 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
13213 { /*lint --e{715}*/
13214  SCIP_CONSHDLRDATA* conshdlrdata;
13215  int c;
13216  int depth;
13217  int nrounds;
13218  int maxsepacuts;
13219  int ncuts;
13220  SCIP_Bool cutoff;
13221 
13222  assert(scip != NULL);
13223  assert(conshdlr != NULL);
13224  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13225  assert(result != NULL);
13227  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13228  assert(conshdlrdata != NULL);
13229  depth = SCIPgetDepth(scip);
13230  nrounds = SCIPgetNSepaRounds(scip);
13231 
13232  /*debugMessage("Sepa method of linear constraints\n");*/
13233 
13234  *result = SCIP_DIDNOTRUN;
13235 
13236  /* only call the separator a given number of times at each node */
13237  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
13238  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
13239  return SCIP_OKAY;
13240 
13241  /* get the maximal number of cuts allowed in a separation round */
13242  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
13243 
13244  *result = SCIP_DIDNOTFIND;
13245  ncuts = 0;
13246  cutoff = FALSE;
13247 
13248  /* check all useful linear constraints for feasibility */
13249  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
13250  {
13251  /*debugMessage("separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
13252  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
13253  }
13254 
13255  /* adjust return value */
13256  if( cutoff )
13257  *result = SCIP_CUTOFF;
13258  else if( ncuts > 0 )
13259  *result = SCIP_SEPARATED;
13260 
13261  /* combine linear constraints to get more cuts */
13262  /**@todo further cuts of linear constraints */
13263 
13264  return SCIP_OKAY;
13265 }
13266 
13267 
13268 /** constraint enforcing method of constraint handler for LP solutions */
13269 static
13270 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
13271 { /*lint --e{715}*/
13272  SCIP_CONSHDLRDATA* conshdlrdata;
13273  SCIP_Bool checkrelmaxabs;
13274  SCIP_Bool violated;
13275  SCIP_Bool cutoff;
13276  int c;
13277 
13278  assert(scip != NULL);
13279  assert(conshdlr != NULL);
13280  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13281  assert(result != NULL);
13282 
13283  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13284  assert(conshdlrdata != NULL);
13285 
13286  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13287 
13288  /*SCIPdebugMessage("Enfolp method of linear constraints\n");*/
13289 
13290  /* check for violated constraints
13291  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
13292  */
13293  *result = SCIP_FEASIBLE;
13294 
13295  /* check all useful linear constraints for feasibility */
13296  for( c = 0; c < nusefulconss; ++c )
13297  {
13298  SCIP_CALL( checkCons(scip, conss[c], NULL, FALSE, checkrelmaxabs, &violated) );
13299 
13300  if( violated )
13301  {
13302  /* insert LP row as cut */
13303  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
13304  if ( cutoff )
13305  *result = SCIP_CUTOFF;
13306  else
13307  *result = SCIP_SEPARATED;
13308  }
13309  }
13310 
13311  /* check all obsolete linear constraints for feasibility */
13312  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
13313  {
13314  SCIP_CALL( checkCons(scip, conss[c], NULL, FALSE, checkrelmaxabs, &violated) );
13315 
13316  if( violated )
13317  {
13318  /* insert LP row as cut */
13319  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
13320  if ( cutoff )
13321  *result = SCIP_CUTOFF;
13322  else
13323  *result = SCIP_SEPARATED;
13324  }
13325  }
13326 
13327  return SCIP_OKAY;
13328 }
13329 
13330 
13331 /** constraint enforcing method of constraint handler for pseudo solutions */
13332 static
13333 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
13334 { /*lint --e{715}*/
13335  SCIP_CONSHDLRDATA* conshdlrdata;
13336  SCIP_Bool checkrelmaxabs;
13337  SCIP_Bool violated;
13338  int c;
13339 
13340  assert(scip != NULL);
13341  assert(conshdlr != NULL);
13342  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13343  assert(result != NULL);
13344 
13345  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13346  assert(conshdlrdata != NULL);
13348  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13349 
13350  SCIPdebugMessage("Enfops method of linear constraints\n");
13351 
13352  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
13353  if( objinfeasible )
13354  {
13355  SCIPdebugMessage("-> pseudo solution is objective infeasible, return.\n");
13356 
13357  *result = SCIP_DIDNOTRUN;
13358  return SCIP_OKAY;
13359  }
13360 
13361  /* check all linear constraints for feasibility */
13362  violated = FALSE;
13363  for( c = 0; c < nconss && !violated; ++c )
13364  {
13365  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
13366  }
13367 
13368  if( violated )
13369  *result = SCIP_INFEASIBLE;
13370  else
13371  *result = SCIP_FEASIBLE;
13372 
13373  SCIPdebugMessage("-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
13374 
13375  return SCIP_OKAY;
13376 }
13377 
13378 
13379 /** feasibility check method of constraint handler for integral solutions */
13380 static
13381 SCIP_DECL_CONSCHECK(consCheckLinear)
13382 { /*lint --e{715}*/
13383  SCIP_CONSHDLRDATA* conshdlrdata;
13384  SCIP_Bool checkrelmaxabs;
13385  SCIP_Bool violated;
13386  int c;
13387 
13388  assert(scip != NULL);
13389  assert(conshdlr != NULL);
13390  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13391  assert(result != NULL);
13392 
13393  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13394  assert(conshdlrdata != NULL);
13396  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13397 
13398  /*debugMessage("Check method of linear constraints\n");*/
13399 
13400  /* check all linear constraints for feasibility */
13401  violated = FALSE;
13402  for( c = 0; c < nconss && !violated; ++c )
13403  {
13404  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
13405  }
13406 
13407  if( violated )
13408  {
13409  *result = SCIP_INFEASIBLE;
13410 
13411  if( printreason )
13412  {
13413  SCIP_CONSDATA* consdata;
13414  SCIP_Real activity;
13415 
13416  consdata = SCIPconsGetData(conss[c-1]);
13417  assert( consdata != NULL);
13418 
13419  activity = consdataGetActivity(scip, consdata, sol);
13420 
13421  SCIP_CALL( SCIPprintCons(scip, conss[c-1], NULL ) );
13422  SCIPinfoMessage(scip, NULL, ";\n");
13423 
13424  if( activity == SCIP_INVALID ) /*lint !e777*/
13425  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
13426  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
13427  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
13428  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
13429  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
13430  }
13431  }
13432  else
13433  *result = SCIP_FEASIBLE;
13434 
13435  return SCIP_OKAY;
13436 }
13437 
13438 
13439 /** domain propagation method of constraint handler */
13440 static
13441 SCIP_DECL_CONSPROP(consPropLinear)
13442 { /*lint --e{715}*/
13443  SCIP_CONSHDLRDATA* conshdlrdata;
13444  SCIP_Bool tightenbounds;
13445  SCIP_Bool cutoff;
13446  int nchgbds;
13447  int i;
13448 
13449  assert(scip != NULL);
13450  assert(conshdlr != NULL);
13451  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13452  assert(result != NULL);
13453 
13454  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13455  assert(conshdlrdata != NULL);
13456 
13457  /*debugMessage("Prop method of linear constraints\n");*/
13458 
13459  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
13460  if( SCIPinProbing(scip) )
13461  tightenbounds = TRUE;
13462  else
13463  {
13464  int depth;
13465  int propfreq;
13466  int tightenboundsfreq;
13467 
13468  depth = SCIPgetDepth(scip);
13469  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
13470  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
13471  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
13472  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
13473  }
13474 
13475  cutoff = FALSE;
13476  nchgbds = 0;
13477 
13478  /* process constraints marked for propagation */
13479  for( i = 0; i < nmarkedconss && !cutoff; i++ )
13480  {
13481  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
13482  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, conshdlrdata->sortvars, &cutoff, &nchgbds) );
13483  }
13484 
13485  /* adjust result code */
13486  if( cutoff )
13487  *result = SCIP_CUTOFF;
13488  else if( nchgbds > 0 )
13489  *result = SCIP_REDUCEDDOM;
13490  else
13491  *result = SCIP_DIDNOTFIND;
13492 
13493  return SCIP_OKAY;
13494 }
13495 
13496 
13497 #define MAXCONSPRESOLROUNDS 10
13498 /** presolving method of constraint handler */
13499 static
13500 SCIP_DECL_CONSPRESOL(consPresolLinear)
13501 { /*lint --e{715}*/
13502  SCIP_CONSHDLRDATA* conshdlrdata;
13503  SCIP_CONS* cons;
13504  SCIP_CONSDATA* consdata;
13505  SCIP_Real minactivity;
13506  SCIP_Real maxactivity;
13507  SCIP_Bool minactisrelax;
13508  SCIP_Bool maxactisrelax;
13509  SCIP_Bool cutoff;
13510  SCIP_Bool delay;
13511  int oldnfixedvars;
13512  int oldnaggrvars;
13513  int oldnchgbds;
13514  int oldndelconss;
13515  int oldnupgdconss;
13516  int oldnchgcoefs;
13517  int oldnchgsides;
13518  int firstchange;
13519  int firstupgradetry;
13520  int c;
13521 
13522  assert(scip != NULL);
13523  assert(conshdlr != NULL);
13524  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13525  assert(result != NULL);
13526 
13527  /*debugMessage("Presol method of linear constraints\n");*/
13528 
13529  /* remember old preprocessing counters */
13530  cutoff = FALSE;
13531  delay = FALSE;
13532  oldnfixedvars = *nfixedvars;
13533  oldnaggrvars = *naggrvars;
13534  oldnchgbds = *nchgbds;
13535  oldndelconss = *ndelconss;
13536  oldnupgdconss = *nupgdconss;
13537  oldnchgcoefs = *nchgcoefs;
13538  oldnchgsides = *nchgsides;
13539 
13540  /* get constraint handler data */
13541  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13542  assert(conshdlrdata != NULL);
13543 
13544  /* process single constraints */
13545  firstchange = INT_MAX;
13546  firstupgradetry = INT_MAX;
13547  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
13548  {
13549  int npresolrounds;
13550  SCIP_Bool infeasible;
13551 
13552  infeasible = FALSE;
13553 
13554  cons = conss[c];
13555  assert(SCIPconsIsActive(cons));
13556  consdata = SCIPconsGetData(cons);
13557  assert(consdata != NULL);
13558 
13559  /* constraint should not be already presolved in the initial round */
13560  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->propagated);
13561  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->boundstightened);
13562  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
13563  assert(consdata->propagated || !consdata->presolved);
13564 
13565  /* incorporate fixings and aggregations in constraint */
13566  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
13567 
13568  if( infeasible )
13569  {
13570  SCIPdebugMessage(" -> infeasible fixing\n");
13571  cutoff = TRUE;
13572  break;
13573  }
13574 
13575  assert(consdata->removedfixings);
13576 
13577  /* we can only presolve linear constraints, that are not modifiable */
13578  if( SCIPconsIsModifiable(cons) )
13579  continue;
13580 
13581  /* remember the first changed constraint to begin the next aggregation round with */
13582  if( firstchange == INT_MAX && consdata->changed )
13583  firstchange = c;
13584 
13585  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
13586  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
13587  firstupgradetry = c;
13588 
13589  /* check, if constraint is already preprocessed */
13590  if( consdata->presolved )
13591  continue;
13592 
13593  assert(SCIPconsIsActive(cons));
13594 
13595  SCIPdebugMessage("presolving linear constraint <%s>\n", SCIPconsGetName(cons));
13596  SCIPdebugPrintCons(scip, cons, NULL);
13597 
13598  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
13599  * to avoid nearly infinite cycling due to very small bound changes)
13600  */
13601  npresolrounds = 0;
13602  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
13603  {
13604  assert(!cutoff);
13605  npresolrounds++;
13606 
13607  /* mark constraint being presolved and propagated */
13608  consdata->presolved = TRUE;
13609  consdata->propagated = TRUE;
13610 
13611  /* normalize constraint */
13612  SCIP_CALL( normalizeCons(scip, cons) );
13613 
13614  /* tighten left and right hand side due to integrality */
13615  SCIP_CALL( tightenSides(scip, cons, nchgsides) );
13616 
13617  /* check bounds */
13618  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13619  {
13620  SCIPdebugMessage("linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13621  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13622  cutoff = TRUE;
13623  break;
13624  }
13625 
13626  /* tighten variable's bounds */
13627  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->sortvars, &cutoff, nchgbds) );
13628  if( cutoff )
13629  break;
13630 
13631  /* check for fixed variables */
13632  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
13633  if( cutoff )
13634  break;
13635 
13636  /* check constraint for infeasibility and redundancy */
13637  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13638  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
13639  {
13640  SCIPdebugMessage("linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13641  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13642  cutoff = TRUE;
13643  break;
13644  }
13645  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
13646  {
13647  SCIPdebugMessage("linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13648  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13649  SCIP_CALL( SCIPdelCons(scip, cons) );
13650  assert(!SCIPconsIsActive(cons));
13651 
13652  if( !consdata->upgraded )
13653  (*ndelconss)++;
13654  break;
13655  }
13656  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
13657  {
13658  SCIPdebugMessage("linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13659  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13660  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
13661  if( !consdata->upgraded )
13662  (*nchgsides)++;
13663  }
13664  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
13665  {
13666  SCIPdebugMessage("linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13667  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13668  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
13669  if( !consdata->upgraded )
13670  (*nchgsides)++;
13671  }
13672  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
13673 
13674  /* handle empty constraint */
13675  if( consdata->nvars == 0 )
13676  {
13677  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13678  {
13679  SCIPdebugMessage("empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13680  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13681  cutoff = TRUE;
13682  }
13683  else
13684  {
13685  SCIPdebugMessage("empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
13686  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13687  SCIP_CALL( SCIPdelCons(scip, cons) );
13688  assert(!SCIPconsIsActive(cons));
13689 
13690  if( !consdata->upgraded )
13691  (*ndelconss)++;
13692  }
13693  break;
13694  }
13695 
13696  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
13697  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
13698 
13699  /* try to simplify inequalities */
13700  if( conshdlrdata->simplifyinequalities )
13701  {
13702  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides) );
13703  }
13704 
13705  /* aggregation variable in equations */
13706  if( conshdlrdata->aggregatevariables )
13707  {
13708  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
13709  if( cutoff )
13710  break;
13711  }
13712  }
13713 
13714  if( !SCIPisStopped(scip) )
13715  {
13716  /* extract cliques from constraint */
13717  if( !cutoff && SCIPconsIsActive(cons) )
13718  {
13719  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->sortvars, nfixedvars, nchgbds, &cutoff) );
13720 
13721  /* check if the constraint got redundant or infeasible */
13722  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
13723  {
13724  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13725  {
13726  SCIPdebugMessage("empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13727  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13728  cutoff = TRUE;
13729  }
13730  else
13731  {
13732  SCIPdebugMessage("empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
13733  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13734  SCIP_CALL( SCIPdelCons(scip, cons) );
13735  assert(!SCIPconsIsActive(cons));
13736 
13737  if( !consdata->upgraded )
13738  (*ndelconss)++;
13739  }
13740  }
13741  }
13742 
13743  /* convert special equalities */
13744  if( !cutoff && SCIPconsIsActive(cons) )
13745  {
13746  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
13747  }
13748 
13749  /* apply dual presolving for variables that appear in only one constraint */
13750  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving )
13751  {
13752  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
13753  }
13754 
13755  /* check if an inequality is parallel to the objective function */
13756  if( !cutoff && SCIPconsIsActive(cons) )
13757  {
13758  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
13759  }
13760 
13761  /* remember the first changed constraint to begin the next aggregation round with */
13762  if( firstchange == INT_MAX && consdata->changed )
13763  firstchange = c;
13764 
13765  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
13766  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
13767  firstupgradetry = c;
13768  }
13769  }
13770 
13771  /* process pairs of constraints: check them for redundancy and try to aggregate them;
13772  * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
13773  * (otherwise, we delay the presolving to be called again next time)
13774  */
13775  if( !cutoff && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
13776  {
13777  if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13778  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides )
13779  {
13780  assert(firstchange >= 0);
13781 
13782  if( firstchange < nconss && conshdlrdata->presolusehashing )
13783  {
13784  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
13785  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
13786  ndelconss, nchgsides) );
13787  }
13788 
13789  if( firstchange < nconss && conshdlrdata->presolpairwise )
13790  {
13791  SCIP_CONS** usefulconss;
13792  int nusefulconss;
13793  int firstchangenew;
13794  SCIP_Longint npaircomparisons;
13795 
13796  npaircomparisons = 0;
13797  oldndelconss = *ndelconss;
13798  oldnchgsides = *nchgsides;
13799  oldnchgcoefs = *nchgcoefs;
13800 
13801  /* allocate temporary memory */
13802  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
13803 
13804  nusefulconss = 0;
13805  firstchangenew = -1;
13806  for( c = 0; c < nconss; ++c )
13807  {
13808  /* update firstchange */
13809  if( c == firstchange )
13810  firstchangenew = nusefulconss;
13811 
13812  /* ignore inactive and modifiable constraints */
13813  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
13814  continue;
13815 
13816  usefulconss[nusefulconss] = conss[c];
13817  ++nusefulconss;
13818  }
13819  firstchange = firstchangenew;
13820  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
13821 
13822  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
13823  {
13824  /* constraint has become inactive or modifiable during pairwise presolving */
13825  if( usefulconss[c] == NULL )
13826  continue;
13827 
13828  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
13829 
13830  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
13831  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
13832  &cutoff, ndelconss, nchgsides, nchgcoefs) );
13833 
13834  if( npaircomparisons > conshdlrdata->nmincomparisons )
13835  {
13836  assert(npaircomparisons > 0);
13837  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
13838  break;
13839  oldndelconss = *ndelconss;
13840  oldnchgsides = *nchgsides;
13841  oldnchgcoefs = *nchgcoefs;
13842  npaircomparisons = 0;
13843  }
13844  }
13845  /* free temporary memory */
13846  SCIPfreeBufferArray(scip, &usefulconss);
13847  }
13848  }
13849  else
13850  delay = TRUE;
13851  }
13852 
13853  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
13854  * in linear constraints and we therefore have full information about it
13855  */
13856  if( !cutoff && firstupgradetry < nconss
13857  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13858  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
13859  )
13860  {
13861  if( conshdlrdata->dualpresolving && !SCIPisStopped(scip) )
13862  {
13863  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
13864  }
13865  }
13866 
13867  /* try to upgrade constraints into a more specific constraint type;
13868  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
13869  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
13870  */
13871  if( !cutoff
13872  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13873  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
13874  )
13875  {
13876  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
13877  {
13878  cons = conss[c];
13879 
13880  /* don't upgrade modifiable constraints */
13881  if( SCIPconsIsModifiable(cons) )
13882  continue;
13883 
13884  consdata = SCIPconsGetData(cons);
13885  assert(consdata != NULL);
13886 
13887  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
13888  if( consdata->upgradetried )
13889  continue;
13890  if( !consdata->presolved )
13891  {
13892  delay = TRUE;
13893  continue;
13894  }
13895 
13896  consdata->upgradetried = TRUE;
13897  if( SCIPconsIsActive(cons) )
13898  {
13899  SCIP_CONS* upgdcons;
13900 
13901  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
13902  if( upgdcons != NULL )
13903  {
13904  /* add the upgraded constraint to the problem */
13905  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
13906  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
13907  (*nupgdconss)++;
13908 
13909  /* mark the linear constraint being upgraded and to be removed after presolving;
13910  * don't delete it directly, because it may help to preprocess other linear constraints
13911  */
13912  assert(!consdata->upgraded);
13913  consdata->upgraded = TRUE;
13914 
13915  /* delete upgraded inequalities immediately;
13916  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
13917  */
13918  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
13919  || !conshdlrdata->presolpairwise
13920  || (conshdlrdata->maxaggrnormscale == 0.0) )
13921  {
13922  SCIP_CALL( SCIPdelCons(scip, cons) );
13923  }
13924  }
13925  }
13926  }
13927  }
13928  else
13929  delay = TRUE;
13930 
13931  /* return the correct result code */
13932  if( cutoff )
13933  *result = SCIP_CUTOFF;
13934  else if( delay )
13935  *result = SCIP_DELAYED;
13936  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
13937  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
13938  *result = SCIP_SUCCESS;
13939  else
13940  *result = SCIP_DIDNOTFIND;
13941 
13942  return SCIP_OKAY;
13943 }
13944 
13945 
13946 /** propagation conflict resolving method of constraint handler */
13947 static
13948 SCIP_DECL_CONSRESPROP(consRespropLinear)
13949 { /*lint --e{715}*/
13950 
13951  assert(scip != NULL);
13952  assert(cons != NULL);
13953  assert(result != NULL);
13954 
13955  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
13956 
13957  return SCIP_OKAY;
13958 }
13959 
13960 
13961 /** variable rounding lock method of constraint handler */
13962 static
13963 SCIP_DECL_CONSLOCK(consLockLinear)
13964 { /*lint --e{715}*/
13965  SCIP_CONSDATA* consdata;
13966  SCIP_Bool haslhs;
13967  SCIP_Bool hasrhs;
13968  int i;
13969 
13970  assert(scip != NULL);
13971  assert(cons != NULL);
13972  consdata = SCIPconsGetData(cons);
13973  assert(consdata != NULL);
13974 
13975  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
13976  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
13978  /* update rounding locks of every single variable */
13979  for( i = 0; i < consdata->nvars; ++i )
13980  {
13981  if( SCIPisPositive(scip, consdata->vals[i]) )
13982  {
13983  if( haslhs )
13984  {
13985  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
13986  }
13987  if( hasrhs )
13988  {
13989  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
13990  }
13991  }
13992  else
13993  {
13994  if( haslhs )
13995  {
13996  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
13997  }
13998  if( hasrhs )
13999  {
14000  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
14001  }
14002  }
14003  }
14004 
14005  return SCIP_OKAY;
14006 }
14007 
14008 
14009 /** variable deletion method of constraint handler */
14010 static
14011 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
14012 {
14013  assert(scip != NULL);
14014  assert(conshdlr != NULL);
14015  assert(conss != NULL || nconss == 0);
14016 
14017  if( nconss > 0 )
14018  {
14019  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
14020  }
14021 
14022  return SCIP_OKAY;
14023 }
14024 
14025 /** constraint display method of constraint handler */
14026 static
14027 SCIP_DECL_CONSPRINT(consPrintLinear)
14028 { /*lint --e{715}*/
14029  assert(scip != NULL);
14030  assert(conshdlr != NULL);
14031  assert(cons != NULL);
14032 
14033  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
14034 
14035  return SCIP_OKAY;
14036 }
14037 
14038 /** constraint copying method of constraint handler */
14039 static
14040 SCIP_DECL_CONSCOPY(consCopyLinear)
14041 { /*lint --e{715}*/
14042  SCIP_VAR** sourcevars;
14043  SCIP_Real* sourcecoefs;
14044  const char* consname;
14045  int nvars;
14046 
14047  assert(scip != NULL);
14048  assert(sourcescip != NULL);
14049  assert(sourcecons != NULL);
14050 
14051  /* get variables and coefficients of the source constraint */
14052  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
14053  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
14054  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
14055 
14056  if( name != NULL )
14057  consname = name;
14058  else
14059  consname = SCIPconsGetName(sourcecons);
14060 
14061  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
14062  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
14063  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
14064  assert(cons != NULL || *valid == FALSE);
14065 
14066  return SCIP_OKAY;
14067 }
14068 
14069 /** constraint parsing method of constraint handler */
14070 static
14071 SCIP_DECL_CONSPARSE(consParseLinear)
14072 { /*lint --e{715}*/
14073  SCIP_VAR** vars;
14074  SCIP_Real* coefs;
14075  int nvars;
14076  int coefssize;
14077  int requsize;
14078  SCIP_Real lhs;
14079  SCIP_Real rhs;
14080  char* endptr;
14081 
14082  assert(scip != NULL);
14083  assert(success != NULL);
14084  assert(str != NULL);
14085  assert(name != NULL);
14086  assert(cons != NULL);
14087 
14088  /* set left and right hand side to their default values */
14089  lhs = -SCIPinfinity(scip);
14090  rhs = SCIPinfinity(scip);
14091 
14092  (*success) = FALSE;
14093 
14094  /* return of string empty */
14095  if( !*str )
14096  return SCIP_OKAY;
14097 
14098  /* ignore whitespace */
14099  while( isspace((unsigned char)*str) )
14100  ++str;
14101 
14102  /* check for left hand side */
14103  if( isdigit((unsigned char)str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit((unsigned char)str[1])) )
14104  {
14105  /* there is a number coming, maybe it is a left-hand-side */
14106  if( !SCIPstrToRealValue(str, &lhs, &endptr) )
14107  {
14108  SCIPerrorMessage("error parsing number from <%s>\n", str);
14109  return SCIP_OKAY;
14110  }
14111 
14112  /* ignore whitespace */
14113  while( isspace((unsigned char)*endptr) )
14114  ++endptr;
14115 
14116  if( endptr[0] != '<' || endptr[1] != '=' )
14117  {
14118  /* no '<=' coming, so it was the first coefficient, but not a left-hand-side */
14119  lhs = -SCIPinfinity(scip);
14120  }
14121  else
14122  {
14123  /* it was indeed a left-hand-side, so continue parsing after it */
14124  str = endptr + 2;
14125 
14126  /* ignore whitespace */
14127  while( isspace((unsigned char)*str) )
14128  ++str;
14129  }
14130  }
14131 
14132  /* initialize buffers for storing the variables and coefficients */
14133  coefssize = 100;
14134  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
14135  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
14136 
14137  /* parse linear sum to get variables and coefficients */
14138  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
14139 
14140  if( *success && requsize > coefssize )
14141  {
14142  /* realloc buffers and try again */
14143  coefssize = requsize;
14144  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
14145  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
14146 
14147  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
14148  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
14149  }
14150 
14151  if( !*success )
14152  {
14153  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", str);
14154  }
14155  else
14156  {
14157  (*success) = FALSE;
14158  str = endptr;
14159 
14160  /* check for left or right hand side */
14161  while( isspace((unsigned char)*str) )
14162  ++str;
14163 
14164  /* check for free constraint */
14165  if( strncmp(str, "[free]", 6) == 0 )
14166  {
14167  if( !SCIPisInfinity(scip, -lhs) )
14168  {
14169  SCIPerrorMessage("cannot have left hand side and [free] status \n");
14170  return SCIP_OKAY;
14171  }
14172  (*success) = TRUE;
14173  }
14174  else
14175  {
14176  switch( *str )
14177  {
14178  case '<':
14179  *success = SCIPstrToRealValue(str+2, &rhs, &endptr);
14180  break;
14181  case '=':
14182  if( !SCIPisInfinity(scip, -lhs) )
14183  {
14184  SCIPerrorMessage("cannot have == on rhs if there was a <= on lhs\n");
14185  return SCIP_OKAY;
14186  }
14187  else
14188  {
14189  *success = SCIPstrToRealValue(str+2, &rhs, &endptr);
14190  lhs = rhs;
14191  }
14192  break;
14193  case '>':
14194  if( !SCIPisInfinity(scip, -lhs) )
14195  {
14196  SCIPerrorMessage("cannot have => on rhs if there was a <= on lhs\n");
14197  return SCIP_OKAY;
14198  }
14199  else
14200  {
14201  *success = SCIPstrToRealValue(str+2, &lhs, &endptr);
14202  break;
14203  }
14204  case '\0':
14205  *success = TRUE;
14206  break;
14207  default:
14208  SCIPerrorMessage("unexpected character %c\n", *str);
14209  return SCIP_OKAY;
14210  }
14211  }
14212 
14213  if( *success )
14214  {
14215  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
14216  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
14217  }
14218  }
14219 
14220  SCIPfreeBufferArray(scip, &coefs);
14221  SCIPfreeBufferArray(scip, &vars);
14222 
14223  return SCIP_OKAY;
14224 }
14225 
14226 
14227 /** constraint method of constraint handler which returns the variables (if possible) */
14228 static
14229 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
14230 { /*lint --e{715}*/
14231  SCIP_CONSDATA* consdata;
14232 
14233  consdata = SCIPconsGetData(cons);
14234  assert(consdata != NULL);
14235 
14236  if( varssize < consdata->nvars )
14237  (*success) = FALSE;
14238  else
14239  {
14240  assert(vars != NULL);
14241 
14242  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
14243  (*success) = TRUE;
14244  }
14245 
14246  return SCIP_OKAY;
14247 }
14248 
14249 /** constraint method of constraint handler which returns the number of variables (if possible) */
14250 static
14251 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
14252 { /*lint --e{715}*/
14253  SCIP_CONSDATA* consdata;
14254 
14255  consdata = SCIPconsGetData(cons);
14256  assert(consdata != NULL);
14257 
14258  (*nvars) = consdata->nvars;
14259  (*success) = TRUE;
14260 
14261  return SCIP_OKAY;
14262 }
14263 
14264 /*
14265  * Callback methods of event handler
14266  */
14267 
14268 static
14269 SCIP_DECL_EVENTEXEC(eventExecLinear)
14270 { /*lint --e{715}*/
14271  SCIP_CONS* cons;
14272  SCIP_CONSDATA* consdata;
14273  SCIP_VAR* var;
14274  SCIP_EVENTTYPE eventtype;
14275 
14276  assert(scip != NULL);
14277  assert(eventhdlr != NULL);
14278  assert(eventdata != NULL);
14279  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
14280  assert(event != NULL);
14281 
14282  cons = eventdata->cons;
14283  assert(cons != NULL);
14284  consdata = SCIPconsGetData(cons);
14285  assert(consdata != NULL);
14286 
14287  eventtype = SCIPeventGetType(event);
14288  var = SCIPeventGetVar(event);
14289 
14290  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
14291  {
14292  SCIP_Real oldbound;
14293  SCIP_Real newbound;
14294  SCIP_Real val;
14295  int varpos;
14296 
14297  varpos = eventdata->varpos;
14298  assert(0 <= varpos && varpos < consdata->nvars);
14299  oldbound = SCIPeventGetOldbound(event);
14300  newbound = SCIPeventGetNewbound(event);
14301  assert(var != NULL);
14302  assert(consdata->vars[varpos] == var);
14303  val = consdata->vals[varpos];
14304 
14305  /* update the activity values */
14306  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
14307  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
14308  else
14309  {
14310  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
14311  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
14312  }
14313 
14314  consdata->presolved = FALSE;
14315 
14316  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
14317  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
14318  {
14319  consdata->propagated = FALSE;
14320  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
14321 
14322  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
14323  if( consdata->maxactdeltavar == var )
14324  {
14325  consdata->maxactdelta = SCIP_INVALID;
14326  consdata->maxactdeltavar = NULL;
14327  }
14328  }
14329  /* update maximal activity delta if a bound was relaxed */
14330  else if( (eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0 && !SCIPisInfinity(scip, consdata->maxactdelta) )
14331  {
14332  SCIP_Real lb;
14333  SCIP_Real ub;
14334  SCIP_Real domain;
14335  SCIP_Real delta;
14336 
14337  lb = SCIPvarGetLbLocal(var);
14338  ub = SCIPvarGetUbLocal(var);
14339 
14340  domain = ub - lb;
14341  delta = REALABS(val) * domain;
14342 
14343  if( delta > consdata->maxactdelta )
14344  {
14345  consdata->maxactdelta = delta;
14346  consdata->maxactdeltavar = var;
14347  }
14348  }
14349 
14350  /* check whether bound tightening might now be successful (if the current bound was relaxed, it might be
14351  * that it can be tightened again)
14352  */
14353  if( consdata->boundstightened )
14354  {
14355  switch( eventtype )
14356  {
14359  consdata->boundstightened = (val > 0.0 && SCIPisInfinity(scip, consdata->rhs))
14360  || (val < 0.0 && SCIPisInfinity(scip, -consdata->lhs));
14361  break;
14364  consdata->boundstightened = (val > 0.0 && SCIPisInfinity(scip, -consdata->lhs))
14365  || (val < 0.0 && SCIPisInfinity(scip, consdata->rhs));
14366  break;
14367  default:
14368  SCIPerrorMessage("invalid event type %d\n", eventtype);
14369  return SCIP_INVALIDDATA;
14370  }
14371  }
14372  }
14373  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
14374  {
14375  /* we want to remove the fixed variable */
14376  consdata->presolved = FALSE;
14377  consdata->removedfixings = FALSE;
14378 
14379  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
14380  if( consdata->maxactdeltavar == var )
14381  {
14382  consdata->maxactdelta = SCIP_INVALID;
14383  consdata->maxactdeltavar = NULL;
14384  }
14385  }
14386 
14387  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
14388  {
14389  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
14390  assert(SCIPvarGetNLocksDown(var) <= 1);
14391  assert(SCIPvarGetNLocksUp(var) <= 1);
14392  consdata->presolved = FALSE;
14393  }
14394  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
14395  {
14396  SCIP_Real oldbound;
14397  SCIP_Real newbound;
14398  SCIP_Real val;
14399  int varpos;
14400 
14401  varpos = eventdata->varpos;
14402  assert(0 <= varpos && varpos < consdata->nvars);
14403  oldbound = SCIPeventGetOldbound(event);
14404  newbound = SCIPeventGetNewbound(event);
14405  assert(var != NULL);
14406  assert(consdata->vars[varpos] == var);
14407  val = consdata->vals[varpos];
14408 
14409  /* update the activity values */
14410  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
14411  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
14412  else
14413  {
14414  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
14415  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
14416  }
14417  }
14418  else
14419  {
14420  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
14421  consdata->varsdeleted = TRUE;
14422  }
14423 
14424  return SCIP_OKAY;
14425 }
14426 
14427 
14428 /*
14429  * Callback methods of conflict handler
14430  */
14431 
14432 static
14433 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
14434 { /*lint --e{715}*/
14435  SCIP_VAR** vars;
14436  SCIP_Real* vals;
14437  SCIP_Real lhs;
14438  int i;
14439 
14440  assert(scip != NULL);
14441  assert(conflicthdlr != NULL);
14442  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
14443  assert(bdchginfos != NULL || nbdchginfos == 0);
14444  assert(result != NULL);
14445 
14446  /* don't process already resolved conflicts */
14447  if( resolved )
14448  {
14449  *result = SCIP_DIDNOTRUN;
14450  return SCIP_OKAY;
14451  }
14452 
14453  *result = SCIP_DIDNOTFIND;
14454 
14455  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
14456  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
14457  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
14458  lhs = 1.0;
14459  for( i = 0; i < nbdchginfos; ++i )
14460  {
14461  assert(bdchginfos != NULL);
14462 
14463  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
14464 
14465  /* we can only treat binary variables */
14466  /**@todo extend linear conflict constraints to some non-binary cases */
14467  if( !SCIPvarIsBinary(vars[i]) )
14468  break;
14469 
14470  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
14471  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
14472  vals[i] = 1.0;
14473  else
14474  {
14475  vals[i] = -1.0;
14476  lhs -= 1.0;
14477  }
14478  }
14479 
14480  if( i == nbdchginfos )
14481  {
14482  SCIP_CONS* cons;
14483  SCIP_CONS* upgdcons;
14484  char consname[SCIP_MAXSTRLEN];
14485 
14486  /* create a constraint out of the conflict set */
14487  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%"SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
14488  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
14489  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
14490 
14491  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
14492  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
14493  if( upgdcons != NULL )
14494  {
14495  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
14496  cons = upgdcons;
14497  }
14498 
14499  /* add constraint to SCIP */
14500  SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
14501  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
14502 
14503  *result = SCIP_CONSADDED;
14504  }
14505 
14506  /* free temporary memory */
14507  SCIPfreeBufferArray(scip, &vals);
14508  SCIPfreeBufferArray(scip, &vars);
14509 
14510  return SCIP_OKAY;
14511 }
14512 
14513 
14514 /*
14515  * Quadratic constraint upgrading
14516  */
14517 
14518 
14519 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
14520  */
14521 static
14522 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
14523 { /*lint --e{715}*/
14524  assert(scip != NULL);
14525  assert(cons != NULL);
14526  assert(nupgdconss != NULL);
14527  assert(upgdconss != NULL);
14528 
14529  *nupgdconss = 0;
14530 
14531  SCIPdebugMessage("upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
14532  SCIPdebugPrintCons(scip, cons, NULL);
14533 
14534  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
14535  return SCIP_OKAY;
14536  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
14537  return SCIP_OKAY;
14538 
14539  if( upgdconsssize < 1 )
14540  {
14541  /* signal that we need more memory */
14542  *nupgdconss = -1;
14543  return SCIP_OKAY;
14544  }
14545 
14546  *nupgdconss = 1;
14547  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
14548  SCIPgetNLinearVarsQuadratic(scip, cons),
14549  SCIPgetLinearVarsQuadratic(scip, cons),
14550  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
14551  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
14555  SCIPconsIsStickingAtNode(cons)) );
14556  SCIPdebugMessage("created linear constraint:\n");
14557  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
14558 
14559  return SCIP_OKAY;
14560 }
14561 
14562 /** tries to upgrade a nonlinear constraint into a linear constraint */
14563 static
14564 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
14565 {
14566  assert(nupgdconss != NULL);
14567  assert(upgdconss != NULL);
14568 
14569  *nupgdconss = 0;
14570 
14571  /* no interest in nonlinear constraints */
14572  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
14573  return SCIP_OKAY;
14574 
14575  /* no interest in constant constraints */
14576  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
14577  return SCIP_OKAY;
14579  if( upgdconsssize < 1 )
14580  {
14581  /* request larger upgdconss array */
14582  *nupgdconss = -1;
14583  return SCIP_OKAY;
14584  }
14585 
14586  *nupgdconss = 1;
14587  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
14589  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
14593  SCIPconsIsStickingAtNode(cons)) );
14594 
14595  return SCIP_OKAY;
14596 }
14597 
14598 /*
14599  * constraint specific interface methods
14600  */
14601 
14602 /** creates the handler for linear constraints and includes it in SCIP */
14604  SCIP* scip /**< SCIP data structure */
14605  )
14606 {
14607  SCIP_CONSHDLRDATA* conshdlrdata;
14608  SCIP_CONSHDLR* conshdlr;
14609  SCIP_EVENTHDLR* eventhdlr;
14610  SCIP_CONFLICTHDLR* conflicthdlr;
14611 
14612  assert(scip != NULL);
14613 
14614  /* create event handler for bound change events */
14616  eventExecLinear, NULL) );
14618  /* create conflict handler for linear constraints */
14620  conflictExecLinear, NULL) );
14621 
14622  /* create constraint handler data */
14623  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
14624 
14625  /* include constraint handler */
14628  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
14629  conshdlrdata) );
14630 
14631  assert(conshdlr != NULL);
14632 
14633  /* set non-fundamental callbacks via specific setter functions */
14634  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
14635  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
14636  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
14637  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
14638  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
14639  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
14640  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
14641  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
14642  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
14643  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
14644  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
14645 #ifdef WITH_PRINTORIGCONSTYPES
14646  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLinear) );
14647 #endif
14648  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
14649  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
14650  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
14651  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
14653  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
14654  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
14656  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
14657 
14658  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
14659  {
14660  /* include function that upgrades quadratic constraint to linear constraints */
14662  }
14663 
14664  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
14665  {
14666  /* include the linear constraint upgrade in the nonlinear constraint handler */
14668  }
14669 
14670  /* add linear constraint handler parameters */
14671  SCIP_CALL( SCIPaddIntParam(scip,
14672  "constraints/"CONSHDLR_NAME"/tightenboundsfreq",
14673  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
14674  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, INT_MAX, NULL, NULL) );
14675  SCIP_CALL( SCIPaddIntParam(scip,
14676  "constraints/"CONSHDLR_NAME"/maxrounds",
14677  "maximal number of separation rounds per node (-1: unlimited)",
14678  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
14679  SCIP_CALL( SCIPaddIntParam(scip,
14680  "constraints/"CONSHDLR_NAME"/maxroundsroot",
14681  "maximal number of separation rounds per node in the root node (-1: unlimited)",
14682  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
14683  SCIP_CALL( SCIPaddIntParam(scip,
14684  "constraints/"CONSHDLR_NAME"/maxsepacuts",
14685  "maximal number of cuts separated per separation round",
14686  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
14687  SCIP_CALL( SCIPaddIntParam(scip,
14688  "constraints/"CONSHDLR_NAME"/maxsepacutsroot",
14689  "maximal number of cuts separated per separation round in the root node",
14690  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
14692  "constraints/"CONSHDLR_NAME"/presolpairwise",
14693  "should pairwise constraint comparison be performed in presolving?",
14694  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
14696  "constraints/"CONSHDLR_NAME"/presolusehashing",
14697  "should hash table be used for detecting redundant constraints in advance",
14698  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
14699  SCIP_CALL( SCIPaddIntParam(scip,
14700  "constraints/"CONSHDLR_NAME"/nmincomparisons",
14701  "number for minimal pairwise presolve comparisons",
14702  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
14704  "constraints/"CONSHDLR_NAME"/mingainpernmincomparisons",
14705  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
14706  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
14708  "constraints/"CONSHDLR_NAME"/maxaggrnormscale",
14709  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
14710  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
14712  "constraints/"CONSHDLR_NAME"/maxcardbounddist",
14713  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
14714  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
14716  "constraints/"CONSHDLR_NAME"/separateall",
14717  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
14718  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
14720  "constraints/"CONSHDLR_NAME"/aggregatevariables",
14721  "should presolving search for aggregations in equations",
14722  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
14724  "constraints/"CONSHDLR_NAME"/simplifyinequalities",
14725  "should presolving try to simplify inequalities",
14726  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
14728  "constraints/"CONSHDLR_NAME"/dualpresolving",
14729  "should dual presolving steps be performed?",
14730  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
14732  "constraints/"CONSHDLR_NAME"/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
14733  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
14735  "constraints/"CONSHDLR_NAME"/checkrelmaxabs",
14736  "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)?",
14737  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
14739  "constraints/"CONSHDLR_NAME"/detectcutoffbound",
14740  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
14741  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
14743  "constraints/"CONSHDLR_NAME"/detectlowerbound",
14744  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
14745  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
14747  "constraints/"CONSHDLR_NAME"/detectpartialobjective",
14748  "should presolving try to detect subsets of constraints parallel to the objective function?",
14749  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
14750 
14751  return SCIP_OKAY;
14752 }
14753 
14754 /** includes a linear constraint update method into the linear constraint handler */
14756  SCIP* scip, /**< SCIP data structure */
14757  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
14758  int priority, /**< priority of upgrading method */
14759  const char* conshdlrname /**< name of the constraint handler */
14760  )
14761 {
14762  SCIP_CONSHDLR* conshdlr;
14763  SCIP_CONSHDLRDATA* conshdlrdata;
14764  SCIP_LINCONSUPGRADE* linconsupgrade;
14765  char paramname[SCIP_MAXSTRLEN];
14766  char paramdesc[SCIP_MAXSTRLEN];
14767 
14768  assert(scip != NULL);
14769  assert(linconsupgd != NULL);
14770  assert(conshdlrname != NULL );
14771 
14772  /* find the linear constraint handler */
14773  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14774  if( conshdlr == NULL )
14775  {
14776  SCIPerrorMessage("linear constraint handler not found\n");
14777  return SCIP_PLUGINNOTFOUND;
14778  }
14779 
14780  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14781  assert(conshdlrdata != NULL);
14782 
14783  /* check if linear constraint update method already exists in constraint handler data */
14784  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
14785  {
14786  /* create a linear constraint upgrade data object */
14787  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
14788 
14789  /* insert linear constraint update method into constraint handler data */
14790  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
14791 
14792  /* adds parameter to turn on and off the upgrading step */
14793  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
14794  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
14796  paramname, paramdesc,
14797  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
14798  }
14799 
14800  return SCIP_OKAY;
14801 }
14802 
14803 /** creates and captures a linear constraint
14804  *
14805  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
14806  */
14808  SCIP* scip, /**< SCIP data structure */
14809  SCIP_CONS** cons, /**< pointer to hold the created constraint */
14810  const char* name, /**< name of constraint */
14811  int nvars, /**< number of nonzeros in the constraint */
14812  SCIP_VAR** vars, /**< array with variables of constraint entries */
14813  SCIP_Real* vals, /**< array with coefficients of constraint entries */
14814  SCIP_Real lhs, /**< left hand side of constraint */
14815  SCIP_Real rhs, /**< right hand side of constraint */
14816  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
14817  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
14818  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
14819  * Usually set to TRUE. */
14820  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
14821  * TRUE for model constraints, FALSE for additional, redundant constraints. */
14822  SCIP_Bool check, /**< should the constraint be checked for feasibility?
14823  * TRUE for model constraints, FALSE for additional, redundant constraints. */
14824  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
14825  * Usually set to TRUE. */
14826  SCIP_Bool local, /**< is constraint only valid locally?
14827  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
14828  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
14829  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
14830  * adds coefficients to this constraint. */
14831  SCIP_Bool dynamic, /**< Is constraint subject to aging?
14832  * Usually set to FALSE. Set to TRUE for own cuts which
14833  * are separated as constraints. */
14834  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
14835  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
14836  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
14837  * if it may be moved to a more global node?
14838  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
14839  )
14840 {
14841  SCIP_CONSHDLRDATA* conshdlrdata;
14842  SCIP_CONSHDLR* conshdlr;
14843  SCIP_CONSDATA* consdata;
14844 
14845  assert(scip != NULL);
14846  assert(cons != NULL);
14847 
14848  /* find the linear constraint handler */
14849  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14850  if( conshdlr == NULL )
14851  {
14852  SCIPerrorMessage("linear constraint handler not found\n");
14853  return SCIP_PLUGINNOTFOUND;
14854  }
14855 
14856  /* get event handler */
14857  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14858  assert(conshdlrdata != NULL);
14859  assert(conshdlrdata->eventhdlr != NULL);
14860 
14861  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
14862  * constraint after presolving we have to ensure that it holds active variables
14863  */
14864  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
14865  {
14866  SCIP_VAR** consvars;
14867  SCIP_Real* consvals;
14868  SCIP_Real constant = 0.0;
14869  int nconsvars;
14870  int requiredsize;
14871 
14872  nconsvars = nvars;
14873  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
14874  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
14875 
14876  /* get active variables for new constraint */
14877  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
14878 
14879  /* if space was not enough we need to resize the buffers */
14880  if( requiredsize > nconsvars )
14881  {
14882  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
14883  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
14884 
14885  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
14886  assert(requiredsize <= nconsvars);
14887  }
14888 
14889  /* adjust sides and check that we do not subtract infinity values */
14890  if( SCIPisInfinity(scip, REALABS(constant)) )
14891  {
14892  if( constant < 0.0 )
14893  {
14894  if( SCIPisInfinity(scip, lhs) )
14895  {
14896  SCIPfreeBufferArray(scip, &consvals);
14897  SCIPfreeBufferArray(scip, &consvars);
14898 
14899  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);
14900 
14901  SCIPABORT();
14902  return SCIP_INVALIDDATA; /*lint !e527*/
14903  }
14904  if( SCIPisInfinity(scip, rhs) )
14905  {
14906  SCIPfreeBufferArray(scip, &consvals);
14907  SCIPfreeBufferArray(scip, &consvars);
14908 
14909  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);
14910 
14911  SCIPABORT();
14912  return SCIP_INVALIDDATA; /*lint !e527*/
14913  }
14914 
14915  lhs = -SCIPinfinity(scip);
14916  rhs = -SCIPinfinity(scip);
14917  }
14918  else
14919  {
14920  if( SCIPisInfinity(scip, -lhs) )
14921  {
14922  SCIPfreeBufferArray(scip, &consvals);
14923  SCIPfreeBufferArray(scip, &consvars);
14924 
14925  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);
14926 
14927  SCIPABORT();
14928  return SCIP_INVALIDDATA; /*lint !e527*/
14929  }
14930  if( SCIPisInfinity(scip, -rhs) )
14931  {
14932  SCIPfreeBufferArray(scip, &consvals);
14933  SCIPfreeBufferArray(scip, &consvars);
14934 
14935  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);
14936 
14937  SCIPABORT();
14938  return SCIP_INVALIDDATA; /*lint !e527*/
14939  }
14940 
14941  lhs = SCIPinfinity(scip);
14942  rhs = SCIPinfinity(scip);
14943  }
14944  }
14945  else
14946  {
14947  if( !SCIPisInfinity(scip, REALABS(lhs)) )
14948  lhs -= constant;
14949  if( !SCIPisInfinity(scip, REALABS(rhs)) )
14950  rhs -= constant;
14951 
14952  if( SCIPisInfinity(scip, -lhs) )
14953  lhs = -SCIPinfinity(scip);
14954  else if( SCIPisInfinity(scip, lhs) )
14955  lhs = SCIPinfinity(scip);
14956 
14957  if( SCIPisInfinity(scip, rhs) )
14958  rhs = SCIPinfinity(scip);
14959  else if( SCIPisInfinity(scip, -rhs) )
14960  rhs = -SCIPinfinity(scip);
14961  }
14962 
14963  /* create constraint data */
14964  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
14965  assert(consdata != NULL);
14966 
14967  SCIPfreeBufferArray(scip, &consvals);
14968  SCIPfreeBufferArray(scip, &consvars);
14969  }
14970  else
14971  {
14972  /* create constraint data */
14973  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
14974  assert(consdata != NULL);
14975  }
14976 
14977  /* create constraint */
14978  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
14979  local, modifiable, dynamic, removable, stickingatnode) );
14980 
14981  if( SCIPisTransformed(scip) && needEvents(scip) )
14982  {
14983  /* catch bound change events of variables */
14984  SCIP_CALL( consCatchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
14985  assert(consdata->eventdata != NULL);
14986  }
14987 
14988  return SCIP_OKAY;
14989 }
14990 
14991 /** creates and captures a linear constraint
14992  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
14993  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
14994  *
14995  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
14996  *
14997  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
14998  */
15000  SCIP* scip, /**< SCIP data structure */
15001  SCIP_CONS** cons, /**< pointer to hold the created constraint */
15002  const char* name, /**< name of constraint */
15003  int nvars, /**< number of nonzeros in the constraint */
15004  SCIP_VAR** vars, /**< array with variables of constraint entries */
15005  SCIP_Real* vals, /**< array with coefficients of constraint entries */
15006  SCIP_Real lhs, /**< left hand side of constraint */
15007  SCIP_Real rhs /**< right hand side of constraint */
15008  )
15009 {
15010  assert(scip != NULL);
15011 
15012  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
15014 
15015  return SCIP_OKAY;
15016 }
15017 
15018 /** creates by copying and captures a linear constraint */
15020  SCIP* scip, /**< target SCIP data structure */
15021  SCIP_CONS** cons, /**< pointer to store the created target constraint */
15022  SCIP* sourcescip, /**< source SCIP data structure */
15023  const char* name, /**< name of constraint */
15024  int nvars, /**< number of variables in source variable array */
15025  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
15026  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
15027  SCIP_Real lhs, /**< left hand side of the linear constraint */
15028  SCIP_Real rhs, /**< right hand side of the linear constraint */
15029  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
15030  * variables of the target SCIP */
15031  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
15032  * target constraints */
15033  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
15034  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
15035  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
15036  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
15037  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
15038  SCIP_Bool local, /**< is constraint only valid locally? */
15039  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
15040  SCIP_Bool dynamic, /**< is constraint subject to aging? */
15041  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
15042  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
15043  * if it may be moved to a more global node? */
15044  SCIP_Bool global, /**< create a global or a local copy? */
15045  SCIP_Bool* valid /**< pointer to store if the copying was valid */
15046  )
15047 {
15048  SCIP_VAR** vars;
15049  SCIP_Real* coefs;
15050 
15051  SCIP_Real constant;
15052  int requiredsize;
15053  int v;
15054 
15055  if( SCIPisGT(scip, lhs, rhs) )
15056  {
15057  *valid = FALSE;
15058  return SCIP_OKAY;
15059  }
15060 
15061  (*valid) = TRUE;
15062 
15063  if( nvars == 0 )
15064  {
15065  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
15066  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
15067  return SCIP_OKAY;
15068  }
15069 
15070  /* duplicate variable array */
15071  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
15072 
15073  /* duplicate coefficient array */
15074  if( sourcecoefs != NULL )
15075  {
15076  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
15077  }
15078  else
15079  {
15080  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
15081  for( v = 0; v < nvars; ++v )
15082  coefs[v] = 1.0;
15083  }
15084 
15085  constant = 0.0;
15086 
15087  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
15088  * the target SCIP
15089  */
15090  if( !SCIPvarIsOriginal(vars[0]) )
15091  {
15092  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
15093 
15094  if( requiredsize > nvars )
15095  {
15096  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
15097  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
15098 
15099  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
15100  assert(requiredsize <= nvars);
15101  }
15102  }
15103  else
15104  {
15105  for( v = 0; v < nvars; ++v )
15106  {
15107  assert(SCIPvarIsOriginal(vars[v]));
15108  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
15109  assert(vars[v] != NULL);
15110  }
15111  }
15112 
15113  /* map variables of the source constraint to variables of the target SCIP */
15114  for( v = 0; v < nvars && *valid; ++v )
15115  {
15116  SCIP_VAR* var;
15117  var = vars[v];
15118 
15119  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, valid) );
15120  assert(!(*valid) || vars[v] != NULL);
15121  }
15122 
15123  /* only create the target constraint, if all variables could be copied */
15124  if( *valid )
15125  {
15126  if( !SCIPisInfinity(scip, -lhs) )
15127  lhs -= constant;
15128 
15129  if( !SCIPisInfinity(scip, rhs) )
15130  rhs -= constant;
15131 
15132  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
15133  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
15134  }
15135 
15136  /* free buffer array */
15137  SCIPfreeBufferArray(scip, &coefs);
15138  SCIPfreeBufferArray(scip, &vars);
15139 
15140  return SCIP_OKAY;
15141 }
15142 
15143 /** adds coefficient to linear constraint (if it is not zero) */
15145  SCIP* scip, /**< SCIP data structure */
15146  SCIP_CONS* cons, /**< constraint data */
15147  SCIP_VAR* var, /**< variable of constraint entry */
15148  SCIP_Real val /**< coefficient of constraint entry */
15149  )
15150 {
15151  assert(scip != NULL);
15152  assert(cons != NULL);
15153  assert(var != NULL);
15154 
15155  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15156  {
15157  SCIPerrorMessage("constraint is not linear\n");
15159  }
15160 
15161  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
15162  * constraint after presolving we have to ensure that it holds active variables
15163  */
15164  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
15165  {
15166  SCIP_CONSDATA* consdata;
15167  SCIP_VAR** consvars;
15168  SCIP_Real* consvals;
15169  SCIP_Real constant = 0.0;
15170  SCIP_Real rhs;
15171  SCIP_Real lhs;
15172  int nconsvars;
15173  int requiredsize;
15174  int v;
15175 
15176  nconsvars = 1;
15177  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
15178  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
15179  consvars[0] = var;
15180  consvals[0] = val;
15181 
15182  /* get active variables for new constraint */
15183  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
15184 
15185  /* if space was not enough we need to resize the buffers */
15186  if( requiredsize > nconsvars )
15187  {
15188  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
15189  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
15190 
15191  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
15192  assert(requiredsize <= nconsvars);
15193  }
15194 
15195  consdata = SCIPconsGetData(cons);
15196  assert(consdata != NULL);
15197 
15198  lhs = consdata->lhs;
15199  rhs = consdata->rhs;
15200 
15201  /* adjust sides and check that we do not subtract infinity values */
15202  /* constant is infinite */
15203  if( SCIPisInfinity(scip, REALABS(constant)) )
15204  {
15205  if( constant < 0.0 )
15206  {
15207  if( SCIPisInfinity(scip, lhs) )
15208  {
15209  SCIPfreeBufferArray(scip, &consvals);
15210  SCIPfreeBufferArray(scip, &consvars);
15211 
15212  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));
15213 
15214  SCIPABORT();
15215  return SCIP_INVALIDDATA; /*lint !e527*/
15216  }
15217  if( SCIPisInfinity(scip, rhs) )
15218  {
15219  SCIPfreeBufferArray(scip, &consvals);
15220  SCIPfreeBufferArray(scip, &consvars);
15221 
15222  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));
15223 
15224  SCIPABORT();
15225  return SCIP_INVALIDDATA; /*lint !e527*/
15226  }
15227 
15228  lhs = -SCIPinfinity(scip);
15229  rhs = -SCIPinfinity(scip);
15230  }
15231  else
15232  {
15233  if( SCIPisInfinity(scip, -lhs) )
15234  {
15235  SCIPfreeBufferArray(scip, &consvals);
15236  SCIPfreeBufferArray(scip, &consvars);
15237 
15238  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));
15239 
15240  SCIPABORT();
15241  return SCIP_INVALIDDATA; /*lint !e527*/
15242  }
15243  if( SCIPisInfinity(scip, -rhs) )
15244  {
15245  SCIPfreeBufferArray(scip, &consvals);
15246  SCIPfreeBufferArray(scip, &consvars);
15247 
15248  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));
15249 
15250  SCIPABORT();
15251  return SCIP_INVALIDDATA; /*lint !e527*/
15252  }
15253 
15254  lhs = SCIPinfinity(scip);
15255  rhs = SCIPinfinity(scip);
15256  }
15257  }
15258  /* constant is not infinite */
15259  else
15260  {
15261  if( !SCIPisInfinity(scip, REALABS(lhs)) )
15262  lhs -= constant;
15263  if( !SCIPisInfinity(scip, REALABS(rhs)) )
15264  rhs -= constant;
15265 
15266  if( SCIPisInfinity(scip, -lhs) )
15267  lhs = -SCIPinfinity(scip);
15268  else if( SCIPisInfinity(scip, lhs) )
15269  lhs = SCIPinfinity(scip);
15270 
15271  if( SCIPisInfinity(scip, rhs) )
15272  rhs = SCIPinfinity(scip);
15273  else if( SCIPisInfinity(scip, -rhs) )
15274  rhs = -SCIPinfinity(scip);
15275  }
15276 
15277  /* add all active variables to constraint */
15278  for( v = nconsvars - 1; v >= 0; --v )
15279  {
15280  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
15281  }
15282 
15283  /* update left and right hand sides */
15284  SCIP_CALL( chgLhs(scip, cons, lhs));
15285  SCIP_CALL( chgRhs(scip, cons, rhs));
15286 
15287  SCIPfreeBufferArray(scip, &consvals);
15288  SCIPfreeBufferArray(scip, &consvars);
15289  }
15290  else
15291  {
15292  SCIP_CALL( addCoef(scip, cons, var, val) );
15293  }
15294 
15295  return SCIP_OKAY;
15296 }
15297 
15298 /** gets left hand side of linear constraint */
15300  SCIP* scip, /**< SCIP data structure */
15301  SCIP_CONS* cons /**< constraint data */
15302  )
15303 {
15304  SCIP_CONSDATA* consdata;
15305 
15306  assert(scip != NULL);
15307  assert(cons != NULL);
15308 
15309  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15310  {
15311  SCIPerrorMessage("constraint is not linear\n");
15312  SCIPABORT();
15313  return SCIP_INVALID; /*lint !e527*/
15314  }
15315 
15316  consdata = SCIPconsGetData(cons);
15317  assert(consdata != NULL);
15318 
15319  return consdata->lhs;
15320 }
15321 
15322 /** gets right hand side of linear constraint */
15324  SCIP* scip, /**< SCIP data structure */
15325  SCIP_CONS* cons /**< constraint data */
15326  )
15327 {
15328  SCIP_CONSDATA* consdata;
15329 
15330  assert(scip != NULL);
15331  assert(cons != NULL);
15332 
15333  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15334  {
15335  SCIPerrorMessage("constraint is not linear\n");
15336  SCIPABORT();
15337  return SCIP_INVALID; /*lint !e527*/
15338  }
15339 
15340  consdata = SCIPconsGetData(cons);
15341  assert(consdata != NULL);
15342 
15343  return consdata->rhs;
15344 }
15345 
15346 /** changes left hand side of linear constraint */
15348  SCIP* scip, /**< SCIP data structure */
15349  SCIP_CONS* cons, /**< constraint data */
15350  SCIP_Real lhs /**< new left hand side */
15351  )
15352 {
15353  assert(scip != NULL);
15354  assert(cons != NULL);
15355 
15356  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15357  {
15358  SCIPerrorMessage("constraint is not linear\n");
15359  return SCIP_INVALIDDATA;
15360  }
15362  SCIP_CALL( chgLhs(scip, cons, lhs) );
15363 
15364  return SCIP_OKAY;
15365 }
15366 
15367 /** changes right hand side of linear constraint */
15369  SCIP* scip, /**< SCIP data structure */
15370  SCIP_CONS* cons, /**< constraint data */
15371  SCIP_Real rhs /**< new right hand side */
15372  )
15373 {
15374  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15375  {
15376  SCIPerrorMessage("constraint is not linear\n");
15377  return SCIP_INVALIDDATA;
15378  }
15379 
15380  SCIP_CALL( chgRhs(scip, cons, rhs) );
15381 
15382  return SCIP_OKAY;
15383 }
15384 
15385 /** gets the number of variables in the linear constraint */
15386 int SCIPgetNVarsLinear(
15387  SCIP* scip, /**< SCIP data structure */
15388  SCIP_CONS* cons /**< constraint data */
15389  )
15390 {
15391  SCIP_CONSDATA* consdata;
15392 
15393  assert(scip != NULL);
15394  assert(cons != NULL);
15395 
15396  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15397  {
15398  SCIPerrorMessage("constraint is not linear\n");
15399  SCIPABORT();
15400  return -1; /*lint !e527*/
15401  }
15402 
15403  consdata = SCIPconsGetData(cons);
15404  assert(consdata != NULL);
15405 
15406  return consdata->nvars;
15407 }
15408 
15409 /** gets the array of variables in the linear constraint; the user must not modify this array! */
15411  SCIP* scip, /**< SCIP data structure */
15412  SCIP_CONS* cons /**< constraint data */
15413  )
15414 {
15415  SCIP_CONSDATA* consdata;
15416 
15417  assert(scip != NULL);
15418  assert(cons != NULL);
15419 
15420  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15421  {
15422  SCIPerrorMessage("constraint is not linear\n");
15423  SCIPABORT();
15424  return NULL; /*lint !e527*/
15425  }
15426 
15427  consdata = SCIPconsGetData(cons);
15428  assert(consdata != NULL);
15429 
15430  return consdata->vars;
15431 }
15432 
15433 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
15435  SCIP* scip, /**< SCIP data structure */
15436  SCIP_CONS* cons /**< constraint data */
15437  )
15438 {
15439  SCIP_CONSDATA* consdata;
15440 
15441  assert(scip != NULL);
15442  assert(cons != NULL);
15443 
15444  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15445  {
15446  SCIPerrorMessage("constraint is not linear\n");
15447  SCIPABORT();
15448  return NULL; /*lint !e527*/
15449  }
15450 
15451  consdata = SCIPconsGetData(cons);
15452  assert(consdata != NULL);
15453 
15454  return consdata->vals;
15455 }
15456 
15457 /** gets the activity of the linear constraint in the given solution
15458  *
15459  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
15460  * comprises positive and negative infinity contributions
15461  */
15463  SCIP* scip, /**< SCIP data structure */
15464  SCIP_CONS* cons, /**< constraint data */
15465  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
15466  )
15467 {
15468  SCIP_CONSDATA* consdata;
15469 
15470  assert(scip != NULL);
15471  assert(cons != NULL);
15472 
15473  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15474  {
15475  SCIPerrorMessage("constraint is not linear\n");
15477  return SCIP_INVALID; /*lint !e527*/
15478  }
15479 
15480  consdata = SCIPconsGetData(cons);
15481  assert(consdata != NULL);
15482 
15483  if( consdata->row != NULL )
15484  return SCIPgetRowSolActivity(scip, consdata->row, sol);
15485  else
15486  return consdataGetActivity(scip, consdata, sol);
15487 }
15488 
15489 /** gets the feasibility of the linear constraint in the given solution */
15491  SCIP* scip, /**< SCIP data structure */
15492  SCIP_CONS* cons, /**< constraint data */
15493  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
15494  )
15495 {
15496  SCIP_CONSDATA* consdata;
15497 
15498  assert(scip != NULL);
15499  assert(cons != NULL);
15500 
15501  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15502  {
15503  SCIPerrorMessage("constraint is not linear\n");
15505  return SCIP_INVALID; /*lint !e527*/
15506  }
15507 
15508  consdata = SCIPconsGetData(cons);
15509  assert(consdata != NULL);
15510 
15511  if( consdata->row != NULL )
15512  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
15513  else
15514  return consdataGetFeasibility(scip, consdata, sol);
15515 }
15516 
15517 /** gets the dual solution of the linear constraint in the current LP */
15519  SCIP* scip, /**< SCIP data structure */
15520  SCIP_CONS* cons /**< constraint data */
15521  )
15522 {
15523  SCIP_CONSDATA* consdata;
15524 
15525  assert(scip != NULL);
15526  assert(cons != NULL);
15527 
15528  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15529  {
15530  SCIPerrorMessage("constraint is not linear\n");
15531  SCIPABORT();
15532  return SCIP_INVALID; /*lint !e527*/
15533  }
15534 
15535  consdata = SCIPconsGetData(cons);
15536  assert(consdata != NULL);
15537 
15538  if( consdata->row != NULL )
15539  return SCIProwGetDualsol(consdata->row);
15540  else
15541  return 0.0;
15542 }
15543 
15544 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
15546  SCIP* scip, /**< SCIP data structure */
15547  SCIP_CONS* cons /**< constraint data */
15548  )
15549 {
15550  SCIP_CONSDATA* consdata;
15551 
15552  assert(scip != NULL);
15553  assert(cons != NULL);
15554 
15555  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15556  {
15557  SCIPerrorMessage("constraint is not linear\n");
15558  SCIPABORT();
15559  return SCIP_INVALID; /*lint !e527*/
15560  }
15561 
15562  consdata = SCIPconsGetData(cons);
15563  assert(consdata != NULL);
15564 
15565  if( consdata->row != NULL )
15566  return SCIProwGetDualfarkas(consdata->row);
15567  else
15568  return 0.0;
15569 }
15570 
15571 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
15572  * the user must not modify the row!
15573  */
15575  SCIP* scip, /**< SCIP data structure */
15576  SCIP_CONS* cons /**< constraint data */
15577  )
15578 {
15579  SCIP_CONSDATA* consdata;
15580 
15581  assert(scip != NULL);
15582  assert(cons != NULL);
15583 
15584  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15585  {
15586  SCIPerrorMessage("constraint is not linear\n");
15587  SCIPABORT();
15588  return NULL; /*lint !e527*/
15589  }
15590 
15591  consdata = SCIPconsGetData(cons);
15592  assert(consdata != NULL);
15593 
15594  return consdata->row;
15595 }
15596 
15597 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
15599  SCIP* scip, /**< SCIP data structure */
15600  SCIP_CONS* cons, /**< source constraint to try to convert */
15601  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
15602  )
15603 {
15604  SCIP_CONSHDLR* conshdlr;
15605  SCIP_CONSHDLRDATA* conshdlrdata;
15606  SCIP_CONSDATA* consdata;
15607  SCIP_VAR* var;
15608  SCIP_Real val;
15609  SCIP_Real lb;
15610  SCIP_Real ub;
15611  SCIP_Real poscoeffsum;
15612  SCIP_Real negcoeffsum;
15613  SCIP_Bool integral;
15614  int nposbin;
15615  int nnegbin;
15616  int nposint;
15617  int nnegint;
15618  int nposimpl;
15619  int nnegimpl;
15620  int nposimplbin;
15621  int nnegimplbin;
15622  int nposcont;
15623  int nnegcont;
15624  int ncoeffspone;
15625  int ncoeffsnone;
15626  int ncoeffspint;
15627  int ncoeffsnint;
15628  int ncoeffspfrac;
15629  int ncoeffsnfrac;
15630  int i;
15631 
15632  assert(scip != NULL);
15633  assert(cons != NULL);
15634  assert(upgdcons != NULL);
15635 
15636  *upgdcons = NULL;
15637 
15638  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
15639  if( SCIPconsIsModifiable(cons) )
15640  return SCIP_OKAY;
15641 
15642  /* check for upgradability */
15643  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
15644  return SCIP_OKAY;
15645 
15646  /* get the constraint handler and check, if it's really a linear constraint */
15647  conshdlr = SCIPconsGetHdlr(cons);
15648  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
15649  {
15650  SCIPerrorMessage("constraint is not linear\n");
15651  return SCIP_INVALIDDATA;
15652  }
15653 
15654  /* get constraint handler data and constraint data */
15655  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15656  assert(conshdlrdata != NULL);
15657  consdata = SCIPconsGetData(cons);
15658  assert(consdata != NULL);
15659 
15660  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
15661  if( consdata->upgraded )
15662  return SCIP_OKAY;
15663 
15664  /* check, if the constraint is already stored as LP row */
15665  if( consdata->row != NULL )
15666  {
15667  if( SCIProwIsInLP(consdata->row) )
15668  {
15669  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
15670  return SCIP_INVALIDDATA;
15671  }
15672  else
15673  {
15674  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15675  }
15676  }
15677 
15678  /* normalize constraint */
15679  SCIP_CALL( normalizeCons(scip, cons) );
15680 
15681 
15682  /*
15683  * calculate some statistics on linear constraint
15684  */
15685 
15686  nposbin = 0;
15687  nnegbin = 0;
15688  nposint = 0;
15689  nnegint = 0;
15690  nposimpl = 0;
15691  nnegimpl = 0;
15692  nposimplbin = 0;
15693  nnegimplbin = 0;
15694  nposcont = 0;
15695  nnegcont = 0;
15696  ncoeffspone = 0;
15697  ncoeffsnone = 0;
15698  ncoeffspint = 0;
15699  ncoeffsnint = 0;
15700  ncoeffspfrac = 0;
15701  ncoeffsnfrac = 0;
15702  integral = TRUE;
15703  poscoeffsum = 0.0;
15704  negcoeffsum = 0.0;
15705 
15706  for( i = 0; i < consdata->nvars; ++i )
15707  {
15708  var = consdata->vars[i];
15709  val = consdata->vals[i];
15710  lb = SCIPvarGetLbLocal(var);
15711  ub = SCIPvarGetUbLocal(var);
15712  assert(!SCIPisZero(scip, val));
15713 
15714  switch( SCIPvarGetType(var) )
15715  {
15716  case SCIP_VARTYPE_BINARY:
15717  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15718  integral = integral && SCIPisIntegral(scip, val);
15719  if( val >= 0.0 )
15720  nposbin++;
15721  else
15722  nnegbin++;
15723  break;
15724  case SCIP_VARTYPE_INTEGER:
15725  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15726  integral = integral && SCIPisIntegral(scip, val);
15727  if( val >= 0.0 )
15728  nposint++;
15729  else
15730  nnegint++;
15731  break;
15732  case SCIP_VARTYPE_IMPLINT:
15733  if( SCIPvarIsBinary(var) )
15734  {
15735  if( val >= 0.0 )
15736  nposimplbin++;
15737  else
15738  nnegimplbin++;
15739  }
15740  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15741  integral = integral && SCIPisIntegral(scip, val);
15742  if( val >= 0.0 )
15743  nposimpl++;
15744  else
15745  nnegimpl++;
15746  break;
15748  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
15749  if( val >= 0.0 )
15750  nposcont++;
15751  else
15752  nnegcont++;
15753  break;
15754  default:
15755  SCIPerrorMessage("unknown variable type\n");
15756  return SCIP_INVALIDDATA;
15757  }
15758  if( SCIPisEQ(scip, val, 1.0) )
15759  ncoeffspone++;
15760  else if( SCIPisEQ(scip, val, -1.0) )
15761  ncoeffsnone++;
15762  else if( SCIPisIntegral(scip, val) )
15763  {
15764  if( SCIPisPositive(scip, val) )
15765  ncoeffspint++;
15766  else
15767  ncoeffsnint++;
15768  }
15769  else
15770  {
15771  if( SCIPisPositive(scip, val) )
15772  ncoeffspfrac++;
15773  else
15774  ncoeffsnfrac++;
15775  }
15776  if( SCIPisPositive(scip, val) )
15777  poscoeffsum += val;
15778  else
15779  negcoeffsum += val;
15780  }
15781 
15782 
15783  /*
15784  * call the upgrading methods
15785  */
15786 
15787  SCIPdebugMessage("upgrading linear constraint <%s> (%d upgrade methods):\n",
15788  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
15789  SCIPdebugMessage(" +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
15790  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
15791  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
15792  poscoeffsum, negcoeffsum, integral);
15793 
15794  /* try all upgrading methods in priority order in case the upgrading step is enable */
15795  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
15796  {
15797  if( conshdlrdata->linconsupgrades[i]->active )
15798  {
15799  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
15800  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
15801  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
15802  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
15803  poscoeffsum, negcoeffsum, integral,
15804  upgdcons) );
15805  }
15806  }
15807 
15808 #ifdef SCIP_DEBUG
15809  if( *upgdcons != NULL )
15810  {
15811  SCIPdebugPrintCons(scip, cons, NULL);
15812  SCIPdebugMessage(" -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
15813  SCIPdebugPrintCons(scip, *upgdcons, NULL);
15814  }
15815 #endif
15816 
15817  return SCIP_OKAY;
15818 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
#define MAXACTIVITYDELTATHR
Definition: cons_linear.c:5488
#define EVENTHDLR_DESC
Definition: cons_linear.c:80
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:30035
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:72
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:20784
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38254
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)
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16183
struct InferInfo INFERINFO
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16205
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38397
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:25984
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10071
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5600
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:7876
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5332
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5219
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23286
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:818
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:366
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:674
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3668
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9639
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:25961
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:2862
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:103
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:91
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:48
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:20892
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:15614
#define CONSHDLR_NAME
Definition: cons_linear.c:61
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:38360
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11962
#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)
Definition: cons_linear.c:8820
#define BINWEIGHT
Definition: cons_linear.c:9282
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:2897
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1374
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:19206
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:1411
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1349
#define MAXSCALEDCOEF
Definition: cons_linear.c:130
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
Definition: cons_linear.c:8428
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:100
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:6113
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:9751
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10913
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:15968
#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:7724
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1206
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:13986
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:4890
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38667
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10026
#define SCIP_MAXSTRLEN
Definition: def.h:196
#define CONSHDLR_DELAYPRESOL
Definition: cons_linear.c:74
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5378
#define SCIP_DECL_CONSINITPRE(x)
Definition: type_cons.h:113
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:4990
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:776
#define NULL
Definition: lpi_spx.cpp:129
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6009
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1111
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:38803
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1842
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:940
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7786
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7618
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5078
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
Definition: scip.c:37789
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
Definition: scip.c:35253
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16380
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2023
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:466
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
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)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:89
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip.c:11674
SCIP_Real SCIPgetHugeValue(SCIP *scip)
Definition: scip.c:38386
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1143
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:22044
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:125
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:15670
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5562
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:2579
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:2955
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:112
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7846
#define FALSE
Definition: def.h:52
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1046
SCIP_DECL_LINCONSUPGD((*linconsupgd))
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:16482
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10116
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7209
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
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:2641
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:546
#define TRUE
Definition: def.h:51
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:106
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7577
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16977
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:93
#define SCIPstatisticMessage
Definition: pub_message.h:104
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5539
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:5919
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
Definition: cons_linear.c:8794
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)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38743
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2666
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_Bool delaypresol)
Definition: scip.c:5271
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:53
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:17775
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:7928
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:14579
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38779
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:35229
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23484
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:25564
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38574
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:19756
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:19185
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides)
Definition: cons_linear.c:7213
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15141
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:94
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:31775
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:7132
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:19214
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:39213
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
enum Proprule PROPRULE
Definition: cons_linear.c:316
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)
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10251
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING timingmask)
Definition: scip.c:5036
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:25459
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip.c:22847
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7776
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7716
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:375
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:23934
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:28256
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:22651
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:710
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1344
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:19215
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:2942
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11177
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:38815
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:109
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:90
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:39054
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:5103
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:35061
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7706
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:77
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:18686
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16136
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:7884
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9527
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:1287
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:22424
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:95
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:66
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:5127
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:3388
#define MAXCONSPRESOLROUNDS
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:15907
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:3414
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:21071
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:56
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:15979
static SCIP_DECL_EVENTEXEC(eventExecLinear)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: scip.c:39312
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:6727
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3893
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:487
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4768
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:5631
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16114
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16987
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:33378
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons_linear.c:8620
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:82
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1096
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)
Constraint handler for knapsack constraints of the form , x binary and .
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:22066
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38273
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:15917
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:115
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
Definition: cons_linear.c:8574
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:15930
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23258
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:1690
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:19183
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:84
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff)
Definition: cons_linear.c:5872
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:38755
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:4821
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:38421
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:2202
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:15319
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:6248
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7816
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:19159
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNSepaRounds(SCIP *scip)
Definition: scip.c:34672
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:19221
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:67
#define SCIPdebugPrintf
Definition: pub_message.h:80
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:19207
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17713
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:23000
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
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:2301
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16125
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:38767
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3873
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:964
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15233
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:21051
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:37705
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1249
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:15989
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38292
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3290
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip.c:17898
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:406
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:37940
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1905
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3028
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7557
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:15999
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1865
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:357
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:7298
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38648
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:15943
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:18848
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:38470
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16009
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
constraint handler for quadratic constraints
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:5247
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:19189
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
Definition: scip.c:38445
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:5684
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3553
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:4686
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:391
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define REALABS(x)
Definition: def.h:146
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons_linear.c:8507
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:576
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:58
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16159
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3214
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:73
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
#define SCIP_CALL(x)
Definition: def.h:258
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:55
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4792
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:24051
#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:4959
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:4936
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:7894
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1526
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:2101
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:3729
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:29454
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38705
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4712
static SCIP_DECL_CONSINIT(consInitLinear)
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:246
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:706
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:49
static SCIP_DECL_CONSTRANS(consTransLinear)
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:97
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7587
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:21023
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:15130
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11302
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
Definition: scip.c:38372
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:19666
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:96
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11453
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:1948
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:120
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:15360
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1007
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16195
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip.c:5493
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:20694
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:1601
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18371
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:15097
#define QUADCONSUPGD_PRIORITY
Definition: cons_linear.c:139
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:983
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3176
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:5223
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:22476
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip.c:22797
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16062
static SCIP_Longint getVarSignature(SCIP_VAR *var)
Definition: cons_linear.c:2883
#define SCIP_Bool
Definition: def.h:49
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:75
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:68
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1174
#define MULTIPLIER
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:3813
static const char * paramname[]
Definition: lpi_msk.c:4129
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1223
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:790
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7796
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:2793
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:5487
constraint handler for nonlinear constraints
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:524
static SCIP_DECL_CONSPROP(consPropLinear)
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:114
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:7650
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22093
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4195
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip.c:11563
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:15570
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
methods for debugging
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7806
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:7676
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1819
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1090
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:16216
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2041
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:140
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static int getVarWeight(SCIP_VAR *var)
Definition: cons_linear.c:9288
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16147
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7567
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:5355
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:34038
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:19167
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:102
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16171
#define MAXDNOM
Definition: cons_linear.c:129
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:57
Constraint handler for linear constraints in their most general form, .
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:1434
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:88
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:94
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:19204
Proprule
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:86
static SCIP_Bool needEvents(SCIP *scip)
Definition: cons_linear.c:807
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:81
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9321
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1256
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:113
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5848
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38330
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1317
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:63
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip.c:14215
#define SCIP_REAL_MAX
Definition: def.h:124
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:18583
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2347
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1170
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:39175
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:33424
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip.c:9413
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5309
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10850
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:131
static SCIP_DECL_CONSCHECK(consCheckLinear)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:501
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:38482
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2922
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:19176
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16370
static SCIP_DECL_CONSPARSE(consParseLinear)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:608
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5516
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:18657
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:3636
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:2428
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip.c:22772
static const SCIP_Real scalars[]
Definition: lp.c:5431
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1239
#define CONTWEIGHT
Definition: cons_linear.c:9284
static SCIP_DECL_CONSLOCK(consLockLinear)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1273
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:744
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
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_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38433
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:19217
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:5492
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:5199
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38686
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17642
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16072
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:7780
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:83
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:3872
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23510
#define SCIP_Real
Definition: def.h:123
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7736
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip.c:22747
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:18477
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:49
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:7838
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:39251
#define MIN(x, y)
Definition: memory.c:59
#define EVENTHDLR_NAME
Definition: cons_linear.c:79
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
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:25276
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
#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)
Definition: cons_linear.c:8739
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4266
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:26010
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38724
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:19198
#define SCIP_INVALID
Definition: def.h:142
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:37733
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
Definition: scip.c:34807
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3406
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:25414
#define CONSHDLR_DESC
Definition: cons_linear.c:62
#define SCIP_Longint
Definition: def.h:107
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip.c:3600
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:431
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:17866
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:245
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip.c:5151
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:17590
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:6181
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1197
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:58
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:48
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16052
int SCIPgetNObjVars(SCIP *scip)
Definition: scip.c:10299
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:348
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define MAXVALRECOMP
Definition: cons_linear.c:7262
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:641
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22156
static SCIP_DECL_CONSPRESOL(consPresolLinear)
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:38001
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:98
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:371
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:54
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:18670
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:38409
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
static SCIP_DECL_CONSEXIT(consExitLinear)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1120
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:3470
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5585
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:19179
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:25540
#define SCIPABORT()
Definition: def.h:230
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7726
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:6595
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:335
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:7886
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7756
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:7896
#define INTWEIGHT
Definition: cons_linear.c:9283
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)
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:3903
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3159
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:25435
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4507
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:6706
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:33573
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:47
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:1769
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:39067
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:92
#define HASHSIZE_LINEARCONS
Definition: cons_linear.c:137
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:1794
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:972
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:98
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:8865