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-2019 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 visit 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 "blockmemshell/memory.h"
50 #include "scip/cons_knapsack.h"
51 #include "scip/cons_linear.h"
52 #include "scip/cons_nonlinear.h"
53 #include "scip/cons_quadratic.h"
54 #include "scip/debug.h"
55 #include "scip/pub_conflict.h"
56 #include "scip/pub_cons.h"
57 #include "scip/pub_event.h"
58 #include "scip/pub_lp.h"
59 #include "scip/pub_message.h"
60 #include "scip/pub_misc.h"
61 #include "scip/pub_misc_sort.h"
62 #include "scip/pub_var.h"
63 #include "scip/scip_branch.h"
64 #include "scip/scip_conflict.h"
65 #include "scip/scip_cons.h"
66 #include "scip/scip_copy.h"
67 #include "scip/scip_cut.h"
68 #include "scip/scip_event.h"
69 #include "scip/scip_general.h"
70 #include "scip/scip_lp.h"
71 #include "scip/scip_mem.h"
72 #include "scip/scip_message.h"
73 #include "scip/scip_numerics.h"
74 #include "scip/scip_param.h"
75 #include "scip/scip_prob.h"
76 #include "scip/scip_probing.h"
77 #include "scip/scip_sol.h"
78 #include "scip/scip_solvingstats.h"
79 #include "scip/scip_tree.h"
80 #include "scip/scip_var.h"
81 #include <ctype.h>
82 #include <string.h>
83 #if defined(_WIN32) || defined(_WIN64)
84 #else
85 #include <strings.h> /*lint --e{766}*/
86 #endif
87 
88 
89 #define CONSHDLR_NAME "linear"
90 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
91 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
92 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
93 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
94 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
95 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
96 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
97  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
98 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
99 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
100 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
101 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
103 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
104 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
106 #define EVENTHDLR_NAME "linear"
107 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
109 #define CONFLICTHDLR_NAME "linear"
110 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
111 #define CONFLICTHDLR_PRIORITY -1000000
113 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
114 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
115 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
116 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
117 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
118 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
119 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
120 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
121 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
122  * comparison round */
123 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
124  * propagation? */
125 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
126  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
127 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
128  * (0.0: disable constraint aggregation) */
129 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
130  * (faster, but numerically less stable) */
131 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
132  * to best node's dual bound for separating knapsack cardinality cuts */
133 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
134  * the ones with non-zero dual value? */
135 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
136 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
137 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
138 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
139 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
140  * constraints using the cheapest variable? */
141 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
142  * function defining an upper bound and prevent these constraints from
143  * entering the LP */
144 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
145  * function defining a lower bound and prevent these constraints from
146  * entering the LP */
147 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
148  * objective function */
149 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
150 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
151 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
152 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
153 
154 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
155  * removed afterwards? */
156 
157 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
158 #define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
159 #define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
160  * type
161  */
162 
163 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
164 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
167 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
168 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
169 
170 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
171  * maybe in fullDualPresolve(), see convertLongEquality()
172  */
175 /** constraint data for linear constraints */
176 struct SCIP_ConsData
177 {
178  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
179  SCIP_Real rhs; /**< right hand side of row */
180  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
181  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
182  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
183  * activity, ignoring the coefficients contributing with infinite value */
184  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
185  * activity, ignoring the coefficients contributing with infinite value */
186  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
187  * over all contributing values */
188  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
189  * over all contributing values */
190  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
191  * activity, ignoring the coefficients contributing with infinite value */
192  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
193  * activity, ignoring the coefficients contributing with infinite value */
194  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
195  * over all contributing values */
196  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
197  * over all contributing values */
198  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
199  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
200  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
201  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
202  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
203  SCIP_VAR** vars; /**< variables of constraint entries */
204  SCIP_Real* vals; /**< coefficients of constraint entries */
205  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
206  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
207  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
208  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
209  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
210  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
211  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
212  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
213  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
214  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
215  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
216  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
217  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
218  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
219  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
220  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
221  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
222  int varssize; /**< size of the vars- and vals-arrays */
223  int nvars; /**< number of nonzeros in constraint */
224  int nbinvars; /**< the number of binary variables in the constraint, only valid after
225  * sorting in stage >= SCIP_STAGE_INITSOLVE
226  */
227  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
228  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
229  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
230  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
231  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
232  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
233  unsigned int validminact:1; /**< is the local minactivity valid? */
234  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
235  unsigned int validglbminact:1; /**< is the global minactivity valid? */
236  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
237  unsigned int presolved:1; /**< is constraint already presolved? */
238  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
239  unsigned int validsignature:1; /**< is the bit signature valid? */
240  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
241  unsigned int normalized:1; /**< is the constraint in normalized form? */
242  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
243  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
244  unsigned int sorted:1; /**< are the constraint's variables sorted? */
245  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
246  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
247  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
248  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
249  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
250  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
251  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
252  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
253  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
254 };
255 
256 /** event data for bound change event */
257 struct SCIP_EventData
258 {
259  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
260  int varpos; /**< position of variable in vars array */
261  int filterpos; /**< position of event in variable's event filter */
262 };
263 
264 /** constraint handler data */
265 struct SCIP_ConshdlrData
266 {
267  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
268  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
269  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
270  * (0.0: disable constraint aggregation) */
271  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
272  * to best node's dual bound for separating knapsack cardinality cuts */
273  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
274  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
275  * (faster, but numerically less stable) */
276  int linconsupgradessize;/**< size of linconsupgrade array */
277  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
278  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
279  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
280  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
281  int maxsepacuts; /**< maximal number of cuts separated per separation round */
282  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
283  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
284  int naddconss; /**< number of added constraints */
285  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
286  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
287  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
288  * the ones with non-zero dual value? */
289  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
290  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
291  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
292  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
293  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
294  * constraints using the cheapest variable? */
295  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
296  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
297  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
298  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
299  * function defining an upper bound and prevent these constraints from
300  * entering the LP */
301  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
302  * function defining a lower bound and prevent these constraints from
303  * entering the LP */
304  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
305  * the objective function */
306  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
307  * infeasibility, and extract sub-constraints from ranged rows and
308  * equations */
309  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
310  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
311  int rangedrowfreq; /**< frequency for applying ranged row propagation */
312  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
313  * removed afterwards? */
314 };
315 
316 /** linear constraint update method */
317 struct SCIP_LinConsUpgrade
318 {
319  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
320  int priority; /**< priority of upgrading method */
321  SCIP_Bool active; /**< is upgrading enabled */
322 };
323 
324 
325 /*
326  * Propagation rules
327  */
328 
329 enum Proprule
330 {
331  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
332  * variable due to the right hand side of the inequality */
333  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
334  * variable due to the left hand side of the inequality */
335  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
336  * single variable in this reanged row */
337  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
338 };
339 typedef enum Proprule PROPRULE;
340 
341 /** inference information */
342 struct InferInfo
343 {
344  union
345  {
346  struct
347  {
348  unsigned int proprule:8; /**< propagation rule that was applied */
349  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
350  } asbits;
351  int asint; /**< inference information as a single int value */
352  } val;
353 };
354 typedef struct InferInfo INFERINFO;
355 
356 /** converts an integer into an inference information */
357 static
359  int i /**< integer to convert */
360  )
361 {
362  INFERINFO inferinfo;
363 
364  inferinfo.val.asint = i;
365 
366  return inferinfo;
367 }
368 
369 /** converts an inference information into an int */
370 static
372  INFERINFO inferinfo /**< inference information to convert */
373  )
374 {
375  return inferinfo.val.asint;
376 }
377 
378 /** returns the propagation rule stored in the inference information */
379 static
381  INFERINFO inferinfo /**< inference information to convert */
382  )
383 {
384  return (int) inferinfo.val.asbits.proprule;
385 }
386 
387 /** returns the position stored in the inference information */
388 static
389 int inferInfoGetPos(
390  INFERINFO inferinfo /**< inference information to convert */
391  )
392 {
393  return (int) inferinfo.val.asbits.pos;
394 }
395 
396 /** constructs an inference information out of a propagation rule and a position number */
397 static
399  PROPRULE proprule, /**< propagation rule that deduced the value */
400  int pos /**< variable position, the propagation rule was applied at */
401  )
402 {
403  INFERINFO inferinfo;
404 
405  assert(pos >= 0);
406  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
407  assert(pos < (1<<24));
408 
409  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
410  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
411 
412  return inferinfo;
413 }
414 
415 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
416 static
417 int getInferInt(
418  PROPRULE proprule, /**< propagation rule that deduced the value */
419  int pos /**< variable position, the propagation rule was applied at */
420  )
421 {
422  return inferInfoToInt(getInferInfo(proprule, pos));
423 }
424 
425 
426 /*
427  * memory growing methods for dynamically allocated arrays
428  */
429 
430 /** ensures, that linconsupgrades array can store at least num entries */
431 static
433  SCIP* scip, /**< SCIP data structure */
434  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
435  int num /**< minimum number of entries to store */
436  )
437 {
438  assert(scip != NULL);
439  assert(conshdlrdata != NULL);
440  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
441 
442  if( num > conshdlrdata->linconsupgradessize )
443  {
444  int newsize;
445 
446  newsize = SCIPcalcMemGrowSize(scip, num);
447  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
448  conshdlrdata->linconsupgradessize = newsize;
449  }
450  assert(num <= conshdlrdata->linconsupgradessize);
451 
452  return SCIP_OKAY;
453 }
454 
455 /** ensures, that vars and vals arrays can store at least num entries */
456 static
458  SCIP* scip, /**< SCIP data structure */
459  SCIP_CONSDATA* consdata, /**< linear constraint data */
460  int num /**< minimum number of entries to store */
461  )
462 {
463  assert(scip != NULL);
464  assert(consdata != NULL);
465  assert(consdata->nvars <= consdata->varssize);
466 
467  if( num > consdata->varssize )
468  {
469  int newsize;
470 
471  newsize = SCIPcalcMemGrowSize(scip, num);
472  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
473  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
474  if( consdata->eventdata != NULL )
475  {
476  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
477  }
478  consdata->varssize = newsize;
479  }
480  assert(num <= consdata->varssize);
481 
482  return SCIP_OKAY;
483 }
484 
485 
486 /*
487  * local methods for managing linear constraint update methods
488  */
489 
490 /** creates a linear constraint upgrade data object */
491 static
493  SCIP* scip, /**< SCIP data structure */
494  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
495  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
496  int priority /**< priority of upgrading method */
497  )
498 {
499  assert(scip != NULL);
500  assert(linconsupgrade != NULL);
501  assert(linconsupgd != NULL);
502 
503  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
504  (*linconsupgrade)->linconsupgd = linconsupgd;
505  (*linconsupgrade)->priority = priority;
506  (*linconsupgrade)->active = TRUE;
507 
508  return SCIP_OKAY;
509 }
510 
511 /** frees a linear constraint upgrade data object */
512 static
513 void linconsupgradeFree(
514  SCIP* scip, /**< SCIP data structure */
515  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
516  )
517 {
518  assert(scip != NULL);
519  assert(linconsupgrade != NULL);
520  assert(*linconsupgrade != NULL);
521 
522  SCIPfreeBlockMemory(scip, linconsupgrade);
523 }
524 
525 /** creates constraint handler data for linear constraint handler */
526 static
528  SCIP* scip, /**< SCIP data structure */
529  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
530  SCIP_EVENTHDLR* eventhdlr /**< event handler */
531  )
532 {
533  assert(scip != NULL);
534  assert(conshdlrdata != NULL);
535  assert(eventhdlr != NULL);
536 
537  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
538  (*conshdlrdata)->linconsupgrades = NULL;
539  (*conshdlrdata)->linconsupgradessize = 0;
540  (*conshdlrdata)->nlinconsupgrades = 0;
541  (*conshdlrdata)->naddconss = 0;
542 
543  /* set event handler for updating linear constraint activity bounds */
544  (*conshdlrdata)->eventhdlr = eventhdlr;
545 
546  return SCIP_OKAY;
547 }
548 
549 /** frees constraint handler data for linear constraint handler */
550 static
551 void conshdlrdataFree(
552  SCIP* scip, /**< SCIP data structure */
553  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
554  )
555 {
556  int i;
557 
558  assert(scip != NULL);
559  assert(conshdlrdata != NULL);
560  assert(*conshdlrdata != NULL);
561 
562  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
563  {
564  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
565  }
566  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
567 
568  SCIPfreeBlockMemory(scip, conshdlrdata);
569 }
570 
571 /** creates a linear constraint upgrade data object */
572 static
574  SCIP* scip, /**< SCIP data structure */
575  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
576  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
577  const char* conshdlrname /**< name of the constraint handler */
578  )
579 {
580  int i;
581 
582  assert(scip != NULL);
583  assert(conshdlrdata != NULL);
584  assert(linconsupgd != NULL);
585  assert(conshdlrname != NULL);
586 
587  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
588  {
589  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
590  {
591 #ifdef SCIP_DEBUG
592  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
593 #endif
594  return TRUE;
595  }
596  }
597 
598  return FALSE;
599 }
600 
601 /** adds a linear constraint update method to the constraint handler's data */
602 static
604  SCIP* scip, /**< SCIP data structure */
605  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
606  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
607  )
608 {
609  int i;
610 
611  assert(scip != NULL);
612  assert(conshdlrdata != NULL);
613  assert(linconsupgrade != NULL);
614 
615  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
616 
617  for( i = conshdlrdata->nlinconsupgrades;
618  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
619  {
620  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
621  }
622  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
623  conshdlrdata->linconsupgrades[i] = linconsupgrade;
624  conshdlrdata->nlinconsupgrades++;
625 
626  return SCIP_OKAY;
627 }
628 
629 /*
630  * local methods
631  */
632 
633 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
634 static
636  SCIP* scip, /**< SCIP data structure */
637  SCIP_CONS* cons, /**< linear constraint */
638  SCIP_VAR* var, /**< variable of constraint entry */
639  SCIP_Real val /**< coefficient of constraint entry */
640  )
641 {
642  SCIP_CONSDATA* consdata;
643 
644  assert(scip != NULL);
645  assert(cons != NULL);
646  assert(var != NULL);
647 
648  consdata = SCIPconsGetData(cons);
649  assert(consdata != NULL);
650  assert(!SCIPisZero(scip, val));
651 
652  if( SCIPisPositive(scip, val) )
653  {
654  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
655  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
656  }
657  else
658  {
659  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
660  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
661  }
662 
663  return SCIP_OKAY;
664 }
665 
666 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
667 static
669  SCIP* scip, /**< SCIP data structure */
670  SCIP_CONS* cons, /**< linear constraint */
671  SCIP_VAR* var, /**< variable of constraint entry */
672  SCIP_Real val /**< coefficient of constraint entry */
673  )
674 {
675  SCIP_CONSDATA* consdata;
676 
677  assert(scip != NULL);
678  assert(cons != NULL);
679  assert(var != NULL);
680 
681  consdata = SCIPconsGetData(cons);
682  assert(consdata != NULL);
683  assert(!SCIPisZero(scip, val));
684 
685  if( SCIPisPositive(scip, val) )
686  {
687  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
688  !SCIPisInfinity(scip, consdata->rhs)) );
689  }
690  else
691  {
692  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
693  !SCIPisInfinity(scip, -consdata->lhs)) );
694  }
695 
696  return SCIP_OKAY;
697 }
698 
699 /** creates event data for variable at given position, and catches events */
700 /**! [SnippetDebugAssertions] */
701 static
703  SCIP* scip, /**< SCIP data structure */
704  SCIP_CONS* cons, /**< linear constraint */
705  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
706  int pos /**< array position of variable to catch bound change events for */
707  )
708 {
709  SCIP_CONSDATA* consdata;
710  assert(scip != NULL);
711  assert(cons != NULL);
712  assert(eventhdlr != NULL);
713 
714  consdata = SCIPconsGetData(cons);
715  assert(consdata != NULL);
716 
717  assert(0 <= pos && pos < consdata->nvars);
718  assert(consdata->vars != NULL);
719  assert(consdata->vars[pos] != NULL);
720  assert(SCIPvarIsTransformed(consdata->vars[pos]));
721  assert(consdata->eventdata != NULL);
722  assert(consdata->eventdata[pos] == NULL);
723 
724  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
725  consdata->eventdata[pos]->cons = cons;
726  consdata->eventdata[pos]->varpos = pos;
727 
728  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
731  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
732 
733  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
734 
735  return SCIP_OKAY;
736 }
737 /**! [SnippetDebugAssertions] */
738 
739 /** deletes event data for variable at given position, and drops events */
740 static
742  SCIP* scip, /**< SCIP data structure */
743  SCIP_CONS* cons, /**< linear constraint */
744  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
745  int pos /**< array position of variable to catch bound change events for */
746  )
747 {
748  SCIP_CONSDATA* consdata;
749  assert(scip != NULL);
750  assert(cons != NULL);
751  assert(eventhdlr != NULL);
752 
753  consdata = SCIPconsGetData(cons);
754  assert(consdata != NULL);
755 
756  assert(0 <= pos && pos < consdata->nvars);
757  assert(consdata->vars[pos] != NULL);
758  assert(consdata->eventdata != NULL);
759  assert(consdata->eventdata[pos] != NULL);
760  assert(consdata->eventdata[pos]->cons == cons);
761  assert(consdata->eventdata[pos]->varpos == pos);
762 
763  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
766  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
767 
768  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
769 
770  return SCIP_OKAY;
771 }
772 
773 /** catches bound change events for all variables in transformed linear constraint */
774 static
776  SCIP* scip, /**< SCIP data structure */
777  SCIP_CONS* cons, /**< linear constraint */
778  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
779  )
780 {
781  SCIP_CONSDATA* consdata;
782  int i;
783 
784  assert(scip != NULL);
785  assert(cons != NULL);
786 
787  consdata = SCIPconsGetData(cons);
788  assert(consdata != NULL);
789  assert(consdata->eventdata == NULL);
790 
791  /* allocate eventdata array */
792  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
793  assert(consdata->eventdata != NULL);
794  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
795 
796  /* catch event for every single variable */
797  for( i = 0; i < consdata->nvars; ++i )
798  {
799  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
800  }
801 
802  return SCIP_OKAY;
803 }
804 
805 /** drops bound change events for all variables in transformed linear constraint */
806 static
808  SCIP* scip, /**< SCIP data structure */
809  SCIP_CONS* cons, /**< linear constraint */
810  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
811  )
812 {
813  SCIP_CONSDATA* consdata;
814  int i;
815 
816  assert(scip != NULL);
817  assert(cons != NULL);
818 
819  consdata = SCIPconsGetData(cons);
820  assert(consdata != NULL);
821  assert(consdata->eventdata != NULL);
822 
823  /* drop event of every single variable */
824  for( i = consdata->nvars - 1; i >= 0; --i )
825  {
826  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
827  }
828 
829  /* free eventdata array */
830  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
831  assert(consdata->eventdata == NULL);
832 
833  return SCIP_OKAY;
834 }
835 
836 /** creates a linear constraint data */
837 static
839  SCIP* scip, /**< SCIP data structure */
840  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
841  int nvars, /**< number of nonzeros in the constraint */
842  SCIP_VAR** vars, /**< array with variables of constraint entries */
843  SCIP_Real* vals, /**< array with coefficients of constraint entries */
844  SCIP_Real lhs, /**< left hand side of row */
845  SCIP_Real rhs /**< right hand side of row */
846  )
847 {
848  int v;
849  SCIP_Real constant;
850 
851  assert(scip != NULL);
852  assert(consdata != NULL);
853  assert(nvars == 0 || vars != NULL);
854  assert(nvars == 0 || vals != NULL);
856  if( SCIPisInfinity(scip, rhs) )
857  rhs = SCIPinfinity(scip);
858  else if( SCIPisInfinity(scip, -rhs) )
859  rhs = -SCIPinfinity(scip);
860 
861  if( SCIPisInfinity(scip, -lhs) )
862  lhs = -SCIPinfinity(scip);
863  else if( SCIPisInfinity(scip, lhs) )
864  lhs = SCIPinfinity(scip);
865 
866  if( SCIPisGT(scip, lhs, rhs) )
867  {
868  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
869  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
870  }
871 
872  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
873 
874  (*consdata)->varssize = 0;
875  (*consdata)->nvars = nvars;
876  (*consdata)->hascontvar = FALSE;
877  (*consdata)->hasnonbinvar = FALSE;
878  (*consdata)->hasnonbinvalid = TRUE;
879  (*consdata)->vars = NULL;
880  (*consdata)->vals = NULL;
881 
882  constant = 0.0;
883  if( nvars > 0 )
884  {
885  int k;
886 
887  SCIP_VAR** varsbuffer;
888  SCIP_Real* valsbuffer;
889 
890  /* copy variables into temporary buffer */
891  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
892  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
893  k = 0;
894 
895  /* loop over variables and sort out fixed ones */
896  for( v = 0; v < nvars; ++v )
897  {
898  SCIP_VAR* var;
899  SCIP_Real val;
900 
901  var = vars[v];
902  val = vals[v];
903 
904  assert(var != NULL);
905  if( !SCIPisZero(scip, val) )
906  {
907  /* treat fixed variable as a constant if problem compression is enabled */
909  {
910  constant += SCIPvarGetLbGlobal(var) * val;
911  }
912  else
913  {
914  varsbuffer[k] = var;
915  valsbuffer[k] = val;
916  k++;
917 
918  /* update hascontvar and hasnonbinvar flags */
919  if( !(*consdata)->hascontvar )
920  {
921  SCIP_VARTYPE vartype = SCIPvarGetType(var);
922 
923  if( vartype != SCIP_VARTYPE_BINARY )
924  {
925  (*consdata)->hasnonbinvar = TRUE;
926 
927  if( vartype == SCIP_VARTYPE_CONTINUOUS )
928  (*consdata)->hascontvar = TRUE;
929  }
930  }
931  }
932  }
933  }
934  (*consdata)->nvars = k;
935 
936  if( k > 0 )
937  {
938  /* copy the possibly reduced buffer arrays into block */
939  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
940  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
941  (*consdata)->varssize = k;
942  }
943  /* free temporary buffer */
944  SCIPfreeBufferArray(scip, &valsbuffer);
945  SCIPfreeBufferArray(scip, &varsbuffer);
946  }
947 
948  (*consdata)->eventdata = NULL;
949 
950  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
951  if( !SCIPisZero(scip, constant) )
952  {
953  if( !SCIPisInfinity(scip, REALABS(lhs)) )
954  lhs -= constant;
955 
956  if( !SCIPisInfinity(scip, REALABS(rhs)) )
957  rhs -= constant;
958  }
959 
960  (*consdata)->row = NULL;
961  (*consdata)->lhs = lhs;
962  (*consdata)->rhs = rhs;
963  (*consdata)->maxabsval = SCIP_INVALID;
964  (*consdata)->minabsval = SCIP_INVALID;
965  (*consdata)->minactivity = SCIP_INVALID;
966  (*consdata)->maxactivity = SCIP_INVALID;
967  (*consdata)->lastminactivity = SCIP_INVALID;
968  (*consdata)->lastmaxactivity = SCIP_INVALID;
969  (*consdata)->maxactdelta = SCIP_INVALID;
970  (*consdata)->maxactdeltavar = NULL;
971  (*consdata)->minactivityneginf = -1;
972  (*consdata)->minactivityposinf = -1;
973  (*consdata)->maxactivityneginf = -1;
974  (*consdata)->maxactivityposinf = -1;
975  (*consdata)->minactivityneghuge = -1;
976  (*consdata)->minactivityposhuge = -1;
977  (*consdata)->maxactivityneghuge = -1;
978  (*consdata)->maxactivityposhuge = -1;
979  (*consdata)->glbminactivity = SCIP_INVALID;
980  (*consdata)->glbmaxactivity = SCIP_INVALID;
981  (*consdata)->lastglbminactivity = SCIP_INVALID;
982  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
983  (*consdata)->glbminactivityneginf = -1;
984  (*consdata)->glbminactivityposinf = -1;
985  (*consdata)->glbmaxactivityneginf = -1;
986  (*consdata)->glbmaxactivityposinf = -1;
987  (*consdata)->glbminactivityneghuge = -1;
988  (*consdata)->glbminactivityposhuge = -1;
989  (*consdata)->glbmaxactivityneghuge = -1;
990  (*consdata)->glbmaxactivityposhuge = -1;
991  (*consdata)->possignature = 0;
992  (*consdata)->negsignature = 0;
993  (*consdata)->validmaxabsval = FALSE;
994  (*consdata)->validminabsval = FALSE;
995  (*consdata)->validactivities = FALSE;
996  (*consdata)->validminact = FALSE;
997  (*consdata)->validmaxact = FALSE;
998  (*consdata)->validglbminact = FALSE;
999  (*consdata)->validglbmaxact = FALSE;
1000  (*consdata)->boundstightened = 0;
1001  (*consdata)->presolved = FALSE;
1002  (*consdata)->removedfixings = FALSE;
1003  (*consdata)->validsignature = FALSE;
1004  (*consdata)->changed = TRUE;
1005  (*consdata)->normalized = FALSE;
1006  (*consdata)->upgradetried = FALSE;
1007  (*consdata)->upgraded = FALSE;
1008  (*consdata)->sorted = (nvars <= 1);
1009  (*consdata)->merged = (nvars <= 1);
1010  (*consdata)->cliquesadded = FALSE;
1011  (*consdata)->implsadded = FALSE;
1012  (*consdata)->binvarssorted = FALSE;
1013  (*consdata)->nbinvars = -1;
1014  (*consdata)->varsdeleted = FALSE;
1015  (*consdata)->rangedrowpropagated = 0;
1016  (*consdata)->checkabsolute = FALSE;
1017 
1018  if( SCIPisTransformed(scip) )
1019  {
1020  /* get transformed variables */
1021  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1022  }
1023 
1024  /* capture variables */
1025  for( v = 0; v < (*consdata)->nvars; v++ )
1026  {
1027  assert((*consdata)->vars[v] != NULL);
1028  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1029  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1030  }
1031 
1032  return SCIP_OKAY;
1033 }
1034 
1035 /** frees a linear constraint data */
1036 static
1038  SCIP* scip, /**< SCIP data structure */
1039  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1040  )
1041 {
1042  int v;
1043 
1044  assert(scip != NULL);
1045  assert(consdata != NULL);
1046  assert(*consdata != NULL);
1047  assert((*consdata)->varssize >= 0);
1048 
1049  /* release the row */
1050  if( (*consdata)->row != NULL )
1051  {
1052  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1053  }
1055  /* release variables */
1056  for( v = 0; v < (*consdata)->nvars; v++ )
1057  {
1058  assert((*consdata)->vars[v] != NULL);
1059  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1060  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1061  }
1062 
1063  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1064  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1065  SCIPfreeBlockMemory(scip, consdata);
1066 
1067  return SCIP_OKAY;
1068 }
1069 
1070 /** prints linear constraint in CIP format to file stream */
1071 static
1073  SCIP* scip, /**< SCIP data structure */
1074  SCIP_CONSDATA* consdata, /**< linear constraint data */
1075  FILE* file /**< output file (or NULL for standard output) */
1076  )
1077 {
1078  assert(scip != NULL);
1079  assert(consdata != NULL);
1080 
1081  /* print left hand side for ranged rows */
1082  if( !SCIPisInfinity(scip, -consdata->lhs)
1083  && !SCIPisInfinity(scip, consdata->rhs)
1084  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1085  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1086 
1087  /* print coefficients and variables */
1088  if( consdata->nvars == 0 )
1089  SCIPinfoMessage(scip, file, "0");
1090  else
1091  {
1092  /* post linear sum of the linear constraint */
1093  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1094  }
1095 
1096  /* print right hand side */
1097  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1098  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1099  else if( !SCIPisInfinity(scip, consdata->rhs) )
1100  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1101  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1102  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1103  else
1104  SCIPinfoMessage(scip, file, " [free]");
1105 
1106  return SCIP_OKAY;
1107 }
1108 
1109 /** prints linear constraint and contained solution values of variables to file stream */
1110 static
1112  SCIP* scip, /**< SCIP data structure */
1113  SCIP_CONS* cons, /**< linear constraint */
1114  SCIP_SOL* sol, /**< solution to print */
1115  FILE* file /**< output file (or NULL for standard output) */
1116  )
1117 {
1118  SCIP_CONSDATA* consdata;
1119 
1120  assert(scip != NULL);
1121  assert(cons != NULL);
1122 
1123  consdata = SCIPconsGetData(cons);
1124  assert(consdata != NULL);
1125 
1127 
1128  /* print left hand side for ranged rows */
1129  if( !SCIPisInfinity(scip, -consdata->lhs)
1130  && !SCIPisInfinity(scip, consdata->rhs)
1131  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1132  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1133 
1134  /* print coefficients and variables */
1135  if( consdata->nvars == 0 )
1136  SCIPinfoMessage(scip, file, "0");
1137  else
1138  {
1139  int v;
1140 
1141  /* post linear sum of the linear constraint */
1142  for( v = 0; v < consdata->nvars; ++v )
1143  {
1144  if( consdata->vals != NULL )
1145  {
1146  if( consdata->vals[v] == 1.0 )
1147  {
1148  if( v > 0 )
1149  SCIPinfoMessage(scip, file, " +");
1150  }
1151  else if( consdata->vals[v] == -1.0 )
1152  SCIPinfoMessage(scip, file, " -");
1153  else
1154  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1155  }
1156  else if( consdata->nvars > 0 )
1157  SCIPinfoMessage(scip, file, " +");
1158 
1159  /* print variable name */
1160  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1161 
1162  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1163  }
1164  }
1165 
1166  /* print right hand side */
1167  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1168  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1169  else if( !SCIPisInfinity(scip, consdata->rhs) )
1170  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1171  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1172  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1173  else
1174  SCIPinfoMessage(scip, file, " [free]");
1175 
1176  SCIPinfoMessage(scip, file, ";\n");
1177 
1178  return SCIP_OKAY;
1179 }
1180 
1181 /** invalidates activity bounds, such that they are recalculated in next get */
1182 static
1184  SCIP_CONSDATA* consdata /**< linear constraint */
1185  )
1186 {
1187  assert(consdata != NULL);
1188 
1189  consdata->validactivities = FALSE;
1190  consdata->validminact = FALSE;
1191  consdata->validmaxact = FALSE;
1192  consdata->validglbminact = FALSE;
1193  consdata->validglbmaxact = FALSE;
1194  consdata->validmaxabsval = FALSE;
1195  consdata->validminabsval = FALSE;
1196  consdata->hasnonbinvalid = FALSE;
1197  consdata->minactivity = SCIP_INVALID;
1198  consdata->maxactivity = SCIP_INVALID;
1199  consdata->lastminactivity = SCIP_INVALID;
1200  consdata->lastmaxactivity = SCIP_INVALID;
1201  consdata->maxabsval = SCIP_INVALID;
1202  consdata->minabsval = SCIP_INVALID;
1203  consdata->maxactdelta = SCIP_INVALID;
1204  consdata->maxactdeltavar = NULL;
1205  consdata->minactivityneginf = -1;
1206  consdata->minactivityposinf = -1;
1207  consdata->maxactivityneginf = -1;
1208  consdata->maxactivityposinf = -1;
1209  consdata->minactivityneghuge = -1;
1210  consdata->minactivityposhuge = -1;
1211  consdata->maxactivityneghuge = -1;
1212  consdata->maxactivityposhuge = -1;
1213  consdata->glbminactivity = SCIP_INVALID;
1214  consdata->glbmaxactivity = SCIP_INVALID;
1215  consdata->lastglbminactivity = SCIP_INVALID;
1216  consdata->lastglbmaxactivity = SCIP_INVALID;
1217  consdata->glbminactivityneginf = -1;
1218  consdata->glbminactivityposinf = -1;
1219  consdata->glbmaxactivityneginf = -1;
1220  consdata->glbmaxactivityposinf = -1;
1221  consdata->glbminactivityneghuge = -1;
1222  consdata->glbminactivityposhuge = -1;
1223  consdata->glbmaxactivityneghuge = -1;
1224  consdata->glbmaxactivityposhuge = -1;
1225 }
1226 
1227 /** compute the pseudo activity of a constraint */
1228 static
1230  SCIP* scip, /**< SCIP data structure */
1231  SCIP_CONSDATA* consdata /**< linear constraint data */
1232  )
1233 {
1234  int i;
1235  int pseudoactivityposinf;
1236  int pseudoactivityneginf;
1237  SCIP_Real pseudoactivity;
1238  SCIP_Real bound;
1239  SCIP_Real val;
1240 
1241  pseudoactivity = 0;
1242  pseudoactivityposinf = 0;
1243  pseudoactivityneginf = 0;
1244 
1245  for( i = consdata->nvars - 1; i >= 0; --i )
1246  {
1247  val = consdata->vals[i];
1248  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1249  if( SCIPisInfinity(scip, bound) )
1250  {
1251  if( val > 0.0 )
1252  pseudoactivityposinf++;
1253  else
1254  pseudoactivityneginf++;
1255  }
1256  else
1257  {
1258  if( SCIPisInfinity(scip, -bound) )
1259  {
1260  if( val > 0.0 )
1261  pseudoactivityneginf++;
1262  else
1263  pseudoactivityposinf++;
1264  }
1265  else
1266  pseudoactivity += val * bound;
1267  }
1268  }
1269 
1270  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1271  return SCIP_INVALID;
1272  else if( pseudoactivityneginf > 0 )
1273  return -SCIPinfinity(scip);
1274  else if( pseudoactivityposinf > 0 )
1275  return SCIPinfinity(scip);
1276 
1277  return pseudoactivity;
1278 }
1279 
1280 /** recompute the minactivity of a constraint */
1281 static
1283  SCIP* scip, /**< SCIP data structure */
1284  SCIP_CONSDATA* consdata /**< linear constraint data */
1285  )
1286 {
1287  int i;
1288  SCIP_Real bound;
1289 
1290  consdata->minactivity = 0;
1291 
1292  for( i = consdata->nvars - 1; i >= 0; --i )
1293  {
1294  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1295  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1296  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1297  consdata->minactivity += consdata->vals[i] * bound;
1298  }
1300  /* the activity was just computed from scratch and is valid now */
1301  consdata->validminact = TRUE;
1302 
1303  /* the activity was just computed from scratch, mark it to be reliable */
1304  consdata->lastminactivity = consdata->minactivity;
1305 }
1306 
1307 /** recompute the maxactivity of a constraint */
1308 static
1310  SCIP* scip, /**< SCIP data structure */
1311  SCIP_CONSDATA* consdata /**< linear constraint data */
1312  )
1313 {
1314  int i;
1315  SCIP_Real bound;
1316 
1317  consdata->maxactivity = 0;
1318 
1319  for( i = consdata->nvars - 1; i >= 0; --i )
1320  {
1321  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1322  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1323  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1324  consdata->maxactivity += consdata->vals[i] * bound;
1325  }
1327  /* the activity was just computed from scratch and is valid now */
1328  consdata->validmaxact = TRUE;
1329 
1330  /* the activity was just computed from scratch, mark it to be reliable */
1331  consdata->lastmaxactivity = consdata->maxactivity;
1332 }
1333 
1334 /** recompute the global minactivity of a constraint */
1335 static
1337  SCIP* scip, /**< SCIP data structure */
1338  SCIP_CONSDATA* consdata /**< linear constraint data */
1339  )
1340 {
1341  int i;
1342  SCIP_Real bound;
1343 
1344  consdata->glbminactivity = 0;
1345 
1346  for( i = consdata->nvars - 1; i >= 0; --i )
1347  {
1348  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1349  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1350  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1351  consdata->glbminactivity += consdata->vals[i] * bound;
1352  }
1354  /* the activity was just computed from scratch and is valid now */
1355  consdata->validglbminact = TRUE;
1356 
1357  /* the activity was just computed from scratch, mark it to be reliable */
1358  consdata->lastglbminactivity = consdata->glbminactivity;
1359 }
1360 
1361 /** recompute the global maxactivity of a constraint */
1362 static
1364  SCIP* scip, /**< SCIP data structure */
1365  SCIP_CONSDATA* consdata /**< linear constraint data */
1366  )
1367 {
1368  int i;
1369  SCIP_Real bound;
1370 
1371  consdata->glbmaxactivity = 0;
1372 
1373  for( i = consdata->nvars - 1; i >= 0; --i )
1374  {
1375  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1376  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1377  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1378  consdata->glbmaxactivity += consdata->vals[i] * bound;
1379  }
1381  /* the activity was just computed from scratch and is valid now */
1382  consdata->validglbmaxact = TRUE;
1383 
1384  /* the activity was just computed from scratch, mark it to be reliable */
1385  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1386 }
1387 
1388 /** calculates maximum absolute value of coefficients */
1389 static
1391  SCIP_CONSDATA* consdata /**< linear constraint data */
1392  )
1393 {
1394  SCIP_Real absval;
1395  int i;
1396 
1397  assert(consdata != NULL);
1398  assert(!consdata->validmaxabsval);
1399  assert(consdata->maxabsval >= SCIP_INVALID);
1400 
1401  consdata->validmaxabsval = TRUE;
1402  consdata->maxabsval = 0.0;
1403  for( i = 0; i < consdata->nvars; ++i )
1404  {
1405  absval = consdata->vals[i];
1406  absval = REALABS(absval);
1407  if( absval > consdata->maxabsval )
1408  consdata->maxabsval = absval;
1409  }
1410 }
1411 
1412 /** calculates minimum absolute value of coefficients */
1413 static
1415  SCIP_CONSDATA* consdata /**< linear constraint data */
1416  )
1417 {
1418  SCIP_Real absval;
1419  int i;
1420 
1421  assert(consdata != NULL);
1422  assert(!consdata->validminabsval);
1423  assert(consdata->minabsval >= SCIP_INVALID);
1424 
1425  consdata->validminabsval = TRUE;
1426 
1427  if( consdata->nvars > 0 )
1428  consdata->minabsval = REALABS(consdata->vals[0]);
1429  else
1430  consdata->minabsval = 0.0;
1432  for( i = 1; i < consdata->nvars; ++i )
1433  {
1434  absval = consdata->vals[i];
1435  absval = REALABS(absval);
1436  if( absval < consdata->minabsval )
1437  consdata->minabsval = absval;
1438  }
1439 }
1440 
1441 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1442 static
1444  SCIP_CONSDATA* consdata /**< linear constraint data */
1445  )
1446 {
1447  int v;
1448 
1449  assert(!consdata->hasnonbinvalid);
1450  consdata->hasnonbinvar = FALSE;
1451  consdata->hascontvar = FALSE;
1452 
1453  for( v = consdata->nvars - 1; v >= 0; --v )
1454  {
1455  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1456 
1457  if( vartype != SCIP_VARTYPE_BINARY )
1458  {
1459  consdata->hasnonbinvar = TRUE;
1461  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1462  {
1463  consdata->hascontvar = TRUE;
1464  break;
1465  }
1466  }
1467  }
1468  assert(consdata->hascontvar || v < 0);
1469 
1470  consdata->hasnonbinvalid = TRUE;
1471 }
1472 
1473 
1474 #ifdef CHECKMAXACTDELTA
1475 /* checks that the stored maximal activity delta (if not invalid) is correct */
1476 static
1478  SCIP* scip, /**< SCIP data structure */
1479  SCIP_CONSDATA* consdata /**< linear constraint data */
1480  )
1481 {
1482  if( consdata->maxactdelta != SCIP_INVALID )
1483  {
1484  SCIP_Real maxactdelta = 0.0;
1485  SCIP_Real domain;
1486  SCIP_Real delta;
1487  SCIP_Real lb;
1488  SCIP_Real ub;
1489  int v;
1490 
1491  for( v = consdata->nvars - 1; v >= 0; --v )
1492  {
1493  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1494  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1495 
1496  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1497  {
1498  maxactdelta = SCIPinfinity(scip);
1499  break;
1500  }
1501 
1502  domain = ub - lb;
1503  delta = REALABS(consdata->vals[v]) * domain;
1504 
1505  if( delta > maxactdelta )
1506  {
1507  maxactdelta = delta;
1508  }
1509  }
1510  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1511  }
1512 }
1513 #else
1514 #define checkMaxActivityDelta(scip, consdata) /**/
1515 #endif
1516 
1517 /** recompute maximal activity contribution for a single variable */
1518 static
1520  SCIP* scip, /**< SCIP data structure */
1521  SCIP_CONSDATA* consdata /**< linear constraint data */
1522  )
1523 {
1524  SCIP_Real delta;
1525  int v;
1526 
1527  consdata->maxactdelta = 0.0;
1528 
1529  if( !consdata->hasnonbinvalid )
1530  consdataCheckNonbinvar(consdata);
1532  /* easy case, the problem consists only of binary variables */
1533  if( !consdata->hasnonbinvar )
1534  {
1535  for( v = consdata->nvars - 1; v >= 0; --v )
1536  {
1537  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1538  {
1539  delta = REALABS(consdata->vals[v]);
1540 
1541  if( delta > consdata->maxactdelta )
1542  {
1543  consdata->maxactdelta = delta;
1544  consdata->maxactdeltavar = consdata->vars[v];
1545  }
1546  }
1547  }
1548  return;
1549  }
1550 
1551  for( v = consdata->nvars - 1; v >= 0; --v )
1552  {
1553  SCIP_Real domain;
1554  SCIP_Real lb;
1555  SCIP_Real ub;
1556 
1557  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1558  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1559 
1560  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1561  {
1562  consdata->maxactdelta = SCIPinfinity(scip);
1563  consdata->maxactdeltavar = consdata->vars[v];
1564  break;
1565  }
1566 
1567  domain = ub - lb;
1568  delta = REALABS(consdata->vals[v]) * domain;
1569 
1570  if( delta > consdata->maxactdelta )
1571  {
1572  consdata->maxactdelta = delta;
1573  consdata->maxactdeltavar = consdata->vars[v];
1574  }
1575  }
1576 }
1577 
1578 
1579 /** updates activities for a change in a bound */
1580 static
1582  SCIP* scip, /**< SCIP data structure */
1583  SCIP_CONSDATA* consdata, /**< linear constraint data */
1584  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1585  SCIP_Real oldbound, /**< old bound of variable */
1586  SCIP_Real newbound, /**< new bound of variable */
1587  SCIP_Real val, /**< coefficient of constraint entry */
1588  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1589  SCIP_Bool global, /**< is it a global or a local bound change? */
1590  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1591  )
1592 {
1593  SCIP_Real* activity;
1594  SCIP_Real* lastactivity;
1595  int* activityposinf;
1596  int* activityneginf;
1597  int* activityposhuge;
1598  int* activityneghuge;
1599  SCIP_Real oldcontribution;
1600  SCIP_Real newcontribution;
1601  SCIP_Real delta;
1602  SCIP_Bool validact;
1603  SCIP_Bool finitenewbound;
1604  SCIP_Bool hugevalnewcont;
1605 
1606  assert(scip != NULL);
1607  assert(consdata != NULL);
1608  assert(global || (var != NULL));
1609  assert(consdata->validactivities);
1610  assert(consdata->minactivity < SCIP_INVALID);
1611  assert(consdata->maxactivity < SCIP_INVALID);
1612  assert(consdata->lastminactivity < SCIP_INVALID);
1613  assert(consdata->lastmaxactivity < SCIP_INVALID);
1614  assert(consdata->minactivityneginf >= 0);
1615  assert(consdata->minactivityposinf >= 0);
1616  assert(consdata->maxactivityneginf >= 0);
1617  assert(consdata->maxactivityposinf >= 0);
1618  assert(consdata->minactivityneghuge >= 0);
1619  assert(consdata->minactivityposhuge >= 0);
1620  assert(consdata->maxactivityneghuge >= 0);
1621  assert(consdata->maxactivityposhuge >= 0);
1622  assert(consdata->glbminactivity < SCIP_INVALID);
1623  assert(consdata->glbmaxactivity < SCIP_INVALID);
1624  assert(consdata->lastglbminactivity < SCIP_INVALID);
1625  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1626  assert(consdata->glbminactivityneginf >= 0);
1627  assert(consdata->glbminactivityposinf >= 0);
1628  assert(consdata->glbmaxactivityneginf >= 0);
1629  assert(consdata->glbmaxactivityposinf >= 0);
1630  assert(consdata->glbminactivityneghuge >= 0);
1631  assert(consdata->glbminactivityposhuge >= 0);
1632  assert(consdata->glbmaxactivityneghuge >= 0);
1633  assert(consdata->glbmaxactivityposhuge >= 0);
1634 
1635  delta = 0.0;
1636 
1637  /* we are updating global activities */
1638  if( global )
1639  {
1640  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1641  * lower bound + pos. coef: update minactivity
1642  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1643  * upper bound + pos. coef: update maxactivity
1644  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1645  */
1646  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1647  {
1648  if( val > 0.0 )
1649  {
1650  activity = &(consdata->glbminactivity);
1651  lastactivity = &(consdata->lastglbminactivity);
1652  activityposinf = &(consdata->glbminactivityposinf);
1653  activityneginf = &(consdata->glbminactivityneginf);
1654  activityposhuge = &(consdata->glbminactivityposhuge);
1655  activityneghuge = &(consdata->glbminactivityneghuge);
1656  validact = consdata->validglbminact;
1657  }
1658  else
1659  {
1660  activity = &(consdata->glbmaxactivity);
1661  lastactivity = &(consdata->lastglbmaxactivity);
1662  activityposinf = &(consdata->glbmaxactivityneginf);
1663  activityneginf = &(consdata->glbmaxactivityposinf);
1664  activityposhuge = &(consdata->glbmaxactivityposhuge);
1665  activityneghuge = &(consdata->glbmaxactivityneghuge);
1666  validact = consdata->validglbmaxact;
1667  }
1668  }
1669  else
1670  {
1671  if( val > 0.0 )
1672  {
1673  activity = &(consdata->glbmaxactivity);
1674  lastactivity = &(consdata->lastglbmaxactivity);
1675  activityposinf = &(consdata->glbmaxactivityposinf);
1676  activityneginf = &(consdata->glbmaxactivityneginf);
1677  activityposhuge = &(consdata->glbmaxactivityposhuge);
1678  activityneghuge = &(consdata->glbmaxactivityneghuge);
1679  validact = consdata->validglbmaxact;
1680  }
1681  else
1682  {
1683  activity = &(consdata->glbminactivity);
1684  lastactivity = &(consdata->lastglbminactivity);
1685  activityposinf = &(consdata->glbminactivityneginf);
1686  activityneginf = &(consdata->glbminactivityposinf);
1687  activityposhuge = &(consdata->glbminactivityposhuge);
1688  activityneghuge = &(consdata->glbminactivityneghuge);
1689  validact = consdata->validglbminact;
1690  }
1691  }
1692  }
1693  /* we are updating local activities */
1694  else
1695  {
1696  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1697  * lower bound + pos. coef: update minactivity
1698  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1699  * upper bound + pos. coef: update maxactivity
1700  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1701  */
1702  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1703  {
1704  if( val > 0.0 )
1705  {
1706  activity = &(consdata->minactivity);
1707  lastactivity = &(consdata->lastminactivity);
1708  activityposinf = &(consdata->minactivityposinf);
1709  activityneginf = &(consdata->minactivityneginf);
1710  activityposhuge = &(consdata->minactivityposhuge);
1711  activityneghuge = &(consdata->minactivityneghuge);
1712  validact = consdata->validminact;
1713  }
1714  else
1715  {
1716  activity = &(consdata->maxactivity);
1717  lastactivity = &(consdata->lastmaxactivity);
1718  activityposinf = &(consdata->maxactivityneginf);
1719  activityneginf = &(consdata->maxactivityposinf);
1720  activityposhuge = &(consdata->maxactivityposhuge);
1721  activityneghuge = &(consdata->maxactivityneghuge);
1722  validact = consdata->validmaxact;
1723  }
1724  }
1725  else
1726  {
1727  if( val > 0.0 )
1728  {
1729  activity = &(consdata->maxactivity);
1730  lastactivity = &(consdata->lastmaxactivity);
1731  activityposinf = &(consdata->maxactivityposinf);
1732  activityneginf = &(consdata->maxactivityneginf);
1733  activityposhuge = &(consdata->maxactivityposhuge);
1734  activityneghuge = &(consdata->maxactivityneghuge);
1735  validact = consdata->validmaxact;
1736  }
1737  else
1738  {
1739  activity = &(consdata->minactivity);
1740  lastactivity = &(consdata->lastminactivity);
1741  activityposinf = &(consdata->minactivityneginf);
1742  activityneginf = &(consdata->minactivityposinf);
1743  activityposhuge = &(consdata->minactivityposhuge);
1744  activityneghuge = &(consdata->minactivityneghuge);
1745  validact = consdata->validminact;
1746  }
1747  }
1748  }
1749 
1750  oldcontribution = val * oldbound;
1751  newcontribution = val * newbound;
1752  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1753  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1754 
1755  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1756  {
1757  /* old bound was +infinity */
1758  if( oldbound > 0.0 )
1759  {
1760  assert((*activityposinf) >= 1);
1761 
1762  /* we only have to do something if the new bound is not again +infinity */
1763  if( finitenewbound || newbound < 0.0 )
1764  {
1765  /* decrease the counter for positive infinite contributions */
1766  (*activityposinf)--;
1767 
1768  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1769  if( !finitenewbound && newbound < 0.0 )
1770  (*activityneginf)++;
1771  else if( hugevalnewcont )
1772  {
1773  /* if the contribution of this variable is too large, increase the counter for huge values */
1774  if( newcontribution > 0.0 )
1775  (*activityposhuge)++;
1776  else
1777  (*activityneghuge)++;
1778  }
1779  /* "normal case": just add the contribution to the activity */
1780  else
1781  delta = newcontribution;
1782  }
1783  }
1784  /* old bound was -infinity */
1785  else
1786  {
1787  assert(oldbound < 0.0);
1788  assert((*activityneginf) >= 1);
1789 
1790  /* we only have to do something ig the new bound is not again -infinity */
1791  if( finitenewbound || newbound > 0.0 )
1792  {
1793  /* decrease the counter for negative infinite contributions */
1794  (*activityneginf)--;
1795 
1796  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1797  if( !finitenewbound && newbound > 0.0 )
1798  (*activityposinf)++;
1799  else if( hugevalnewcont )
1800  {
1801  /* if the contribution of this variable is too large, increase the counter for huge values */
1802  if( newcontribution > 0.0 )
1803  (*activityposhuge)++;
1804  else
1805  (*activityneghuge)++;
1806  }
1807  /* "normal case": just add the contribution to the activity */
1808  else
1809  delta = newcontribution;
1810  }
1811  }
1812  }
1813  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1814  {
1815  /* old contribution was too large and positive */
1816  if( oldcontribution > 0.0 )
1817  {
1818  assert((*activityposhuge) >= 1);
1819 
1820  /* decrease the counter for huge positive contributions; it might be increased again later,
1821  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1822  */
1823  (*activityposhuge)--;
1824 
1825  if( !finitenewbound )
1826  {
1827  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1828  if( newbound > 0.0 )
1829  (*activityposinf)++;
1830  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1831  else
1832  (*activityneginf)++;
1833  }
1834  else if( hugevalnewcont )
1835  {
1836  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1837  if( newcontribution > 0.0 )
1838  (*activityposhuge)++;
1839  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1840  else
1841  (*activityneghuge)++;
1842  }
1843  /* "normal case": just add the contribution to the activity */
1844  else
1845  delta = newcontribution;
1846  }
1847  /* old contribution was too large and negative */
1848  else
1849  {
1850  assert(oldcontribution < 0.0);
1851  assert((*activityneghuge) >= 1);
1852 
1853  /* decrease the counter for huge negative contributions; it might be increased again later,
1854  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1855  */
1856  (*activityneghuge)--;
1857 
1858  if( !finitenewbound )
1859  {
1860  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1861  if( newbound > 0.0 )
1862  (*activityposinf)++;
1863  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1864  else
1865  (*activityneginf)++;
1866  }
1867  else if( hugevalnewcont )
1868  {
1869  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1870  if( newcontribution > 0.0 )
1871  (*activityposhuge)++;
1872  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1873  else
1874  (*activityneghuge)++;
1875  }
1876  /* "normal case": just add the contribution to the activity */
1877  else
1878  delta = newcontribution;
1879  }
1880  }
1881  /* old bound was finite and not too large */
1882  else
1883  {
1884  if( !finitenewbound )
1885  {
1886  /* if the new bound is +infinity, the old contribution has to be subtracted
1887  * and the counter for positive infinite contributions has to be increased
1888  */
1889  if( newbound > 0.0 )
1890  {
1891  (*activityposinf)++;
1892  delta = -oldcontribution;
1893  }
1894  /* if the new bound is -infinity, the old contribution has to be subtracted
1895  * and the counter for negative infinite contributions has to be increased
1896  */
1897  else
1898  {
1899  assert(newbound < 0.0 );
1900 
1901  (*activityneginf)++;
1902  delta = -oldcontribution;
1903  }
1904  }
1905  /* if the contribution of this variable is too large, increase the counter for huge values */
1906  else if( hugevalnewcont )
1907  {
1908  if( newcontribution > 0.0 )
1909  {
1910  (*activityposhuge)++;
1911  delta = -oldcontribution;
1912  }
1913  else
1914  {
1915  (*activityneghuge)++;
1916  delta = -oldcontribution;
1917  }
1918  }
1919  /* "normal case": just update the activity */
1920  else
1921  delta = newcontribution - oldcontribution;
1922  }
1923 
1924  /* update the activity, if the current value is valid and there was a change in the finite part */
1925  if( validact && (delta != 0.0) )
1926  {
1927  /* if the absolute value of the activity is increased, this is regarded as reliable,
1928  * otherwise, we check whether we can still trust the updated value
1929  */
1930  (*activity) = (*activity) + delta;
1931  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1932 
1933  if( REALABS((*lastactivity)) < REALABS(*activity) )
1934  {
1935  (*lastactivity) = (*activity);
1936  }
1937  else
1938  {
1939  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1940  {
1941  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1942  (global ? "global " : ""), (*activity));
1943 
1944  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1945  if( global )
1946  {
1947  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1948  consdata->validglbminact = FALSE;
1949  else
1950  consdata->validglbmaxact = FALSE;
1951  }
1952  else
1953  {
1954  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1955  consdata->validminact = FALSE;
1956  else
1957  consdata->validmaxact = FALSE;
1958  }
1959  }
1960  }
1961  }
1962 }
1963 
1964 /** updates minimum and maximum activity for a change in lower bound */
1965 static
1967  SCIP* scip, /**< SCIP data structure */
1968  SCIP_CONSDATA* consdata, /**< linear constraint data */
1969  SCIP_VAR* var, /**< variable that has been changed */
1970  SCIP_Real oldlb, /**< old lower bound of variable */
1971  SCIP_Real newlb, /**< new lower bound of variable */
1972  SCIP_Real val, /**< coefficient of constraint entry */
1973  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1974  )
1975 {
1976  assert(scip != NULL);
1977  assert(consdata != NULL);
1978  assert(var != NULL);
1979 
1980  if( consdata->validactivities )
1981  {
1982  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1984  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1985  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1986  }
1987 }
1988 
1989 /** updates minimum and maximum activity for a change in upper bound */
1990 static
1992  SCIP* scip, /**< SCIP data structure */
1993  SCIP_CONSDATA* consdata, /**< linear constraint data */
1994  SCIP_VAR* var, /**< variable that has been changed */
1995  SCIP_Real oldub, /**< old upper bound of variable */
1996  SCIP_Real newub, /**< new upper bound of variable */
1997  SCIP_Real val, /**< coefficient of constraint entry */
1998  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1999  )
2000 {
2001  assert(scip != NULL);
2002  assert(consdata != NULL);
2003  assert(var != NULL);
2004 
2005  if( consdata->validactivities )
2006  {
2007  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2009  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
2010  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
2011  }
2012 }
2013 
2014 /** updates minimum and maximum global activity for a change in the global lower bound */
2015 static
2017  SCIP* scip, /**< SCIP data structure */
2018  SCIP_CONSDATA* consdata, /**< linear constraint data */
2019  SCIP_Real oldlb, /**< old lower bound of variable */
2020  SCIP_Real newlb, /**< new lower bound of variable */
2021  SCIP_Real val, /**< coefficient of constraint entry */
2022  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2023  )
2024 {
2025  assert(scip != NULL);
2026  assert(consdata != NULL);
2027 
2028  if( consdata->validactivities )
2029  {
2030  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2031 
2032  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2033  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2034  }
2035 }
2036 
2037 /** updates minimum and maximum global activity for a change in global upper bound */
2038 static
2040  SCIP* scip, /**< SCIP data structure */
2041  SCIP_CONSDATA* consdata, /**< linear constraint data */
2042  SCIP_Real oldub, /**< old upper bound of variable */
2043  SCIP_Real newub, /**< new upper bound of variable */
2044  SCIP_Real val, /**< coefficient of constraint entry */
2045  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2046  )
2047 {
2048  assert(scip != NULL);
2049  assert(consdata != NULL);
2050 
2051  if( consdata->validactivities )
2052  {
2053  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2054 
2055  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2056  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2057  }
2058 }
2059 
2060 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2061 static
2063  SCIP* scip, /**< SCIP data structure */
2064  SCIP_CONSDATA* consdata, /**< linear constraint data */
2065  SCIP_VAR* var, /**< variable of constraint entry */
2066  SCIP_Real val, /**< coefficient of constraint entry */
2067  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2068  )
2069 {
2070  assert(scip != NULL);
2071  assert(consdata != NULL);
2072  assert(var != NULL);
2073 
2074  /* update maximum absolute value */
2075  if( consdata->validmaxabsval )
2076  {
2077  SCIP_Real absval;
2078 
2079  assert(consdata->maxabsval < SCIP_INVALID);
2080 
2081  absval = REALABS(val);
2082  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2083  }
2084 
2085  if( consdata->validminabsval )
2086  {
2087  SCIP_Real absval;
2088 
2089  assert(consdata->minabsval < SCIP_INVALID);
2090 
2091  absval = REALABS(val);
2092  consdata->minabsval = MIN(consdata->minabsval, absval);
2093  }
2094 
2095  /* update minimal and maximal activity */
2096  if( consdata->validactivities )
2097  {
2098  assert(consdata->minactivity < SCIP_INVALID);
2099  assert(consdata->maxactivity < SCIP_INVALID);
2100  assert(consdata->glbminactivity < SCIP_INVALID);
2101  assert(consdata->glbmaxactivity < SCIP_INVALID);
2102 
2103  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2104  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2105  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2106  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2107  }
2108 }
2109 
2110 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2111 static
2113  SCIP* scip, /**< SCIP data structure */
2114  SCIP_CONSDATA* consdata, /**< linear constraint data */
2115  SCIP_VAR* var, /**< variable of constraint entry */
2116  SCIP_Real val, /**< coefficient of constraint entry */
2117  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2118  )
2119 {
2120  assert(scip != NULL);
2121  assert(consdata != NULL);
2122  assert(var != NULL);
2123 
2124  /* invalidate maximum absolute value, if this coefficient was the maximum */
2125  if( consdata->validmaxabsval )
2126  {
2127  SCIP_Real absval;
2128 
2129  absval = REALABS(val);
2130 
2131  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2132  {
2133  consdata->validmaxabsval = FALSE;
2134  consdata->maxabsval = SCIP_INVALID;
2135  }
2136  }
2137 
2138  /* invalidate minimum absolute value, if this coefficient was the minimum */
2139  if( consdata->validminabsval )
2140  {
2141  SCIP_Real absval;
2142 
2143  absval = REALABS(val);
2144 
2145  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2146  {
2147  consdata->validminabsval = FALSE;
2148  consdata->minabsval = SCIP_INVALID;
2149  }
2150  }
2151 
2152  /* update minimal and maximal activity */
2153  if( consdata->validactivities )
2154  {
2155  assert(consdata->minactivity < SCIP_INVALID);
2156  assert(consdata->maxactivity < SCIP_INVALID);
2157  assert(consdata->glbminactivity < SCIP_INVALID);
2158  assert(consdata->glbmaxactivity < SCIP_INVALID);
2159 
2160  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2161  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2162  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2163  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2164  }
2165 }
2166 
2167 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2168 static
2170  SCIP* scip, /**< SCIP data structure */
2171  SCIP_CONSDATA* consdata, /**< linear constraint data */
2172  SCIP_VAR* var, /**< variable of constraint entry */
2173  SCIP_Real oldval, /**< old coefficient of constraint entry */
2174  SCIP_Real newval, /**< new coefficient of constraint entry */
2175  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2176  )
2177 {
2178  assert(scip != NULL);
2179  assert(consdata != NULL);
2180  assert(var != NULL);
2181 
2182  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2183  assert(!SCIPisZero(scip, oldval));
2184 
2185  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2186  assert(!SCIPisZero(scip, newval));
2187 
2188  /* update maximum absolute value */
2189  if( consdata->validmaxabsval )
2190  {
2191  SCIP_Real absval;
2192 
2193  absval = REALABS(newval);
2194 
2195  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2196  {
2197  consdata->maxabsval = absval;
2198  }
2199  else
2200  {
2201  absval = REALABS(oldval);
2202 
2203  /* invalidate maximum absolute value */
2204  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2205  {
2206  consdata->validmaxabsval = FALSE;
2207  consdata->maxabsval = SCIP_INVALID;
2208  }
2209  }
2210  }
2211 
2212  /* update minimum absolute value */
2213  if( consdata->validminabsval )
2214  {
2215  SCIP_Real absval;
2216 
2217  absval = REALABS(newval);
2218 
2219  if( SCIPisLE(scip, absval, consdata->minabsval) )
2220  {
2221  consdata->minabsval = absval;
2222  }
2223  else
2224  {
2225  absval = REALABS(oldval);
2226 
2227  /* invalidate minimum absolute value */
2228  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2229  {
2230  consdata->validminabsval = FALSE;
2231  consdata->minabsval = SCIP_INVALID;
2232  }
2233  }
2234  }
2235 
2236  /* update maximum activity delta */
2237  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2238  {
2239  SCIP_Real domain;
2240  SCIP_Real delta;
2241 
2242  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2243  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2244 
2245  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2246  delta = REALABS(newval) * domain;
2247 
2248  if( delta > consdata->maxactdelta )
2249  {
2250  consdata->maxactdelta = delta;
2251  consdata->maxactdeltavar = var;
2252  }
2253  else
2254  {
2255  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2256  if( consdata->maxactdeltavar == var )
2257  consdata->maxactdelta = SCIP_INVALID;
2258  }
2259  }
2260 
2261  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2262  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2263  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2264 }
2265 
2266 /** returns the maximum absolute value of all coefficients in the constraint */
2267 static
2269  SCIP_CONSDATA* consdata /**< linear constraint data */
2270  )
2271 {
2272  assert(consdata != NULL);
2273 
2274  if( !consdata->validmaxabsval )
2275  consdataCalcMaxAbsval(consdata);
2276  assert(consdata->validmaxabsval);
2277  assert(consdata->maxabsval < SCIP_INVALID);
2278 
2279  return consdata->maxabsval;
2280 }
2281 
2282 /** returns the minimum absolute value of all coefficients in the constraint */
2283 static
2285  SCIP_CONSDATA* consdata /**< linear constraint data */
2286  )
2287 {
2288  assert(consdata != NULL);
2289 
2290  if( !consdata->validminabsval )
2291  consdataCalcMinAbsval(consdata);
2292  assert(consdata->validminabsval);
2293  assert(consdata->minabsval < SCIP_INVALID);
2294 
2295  return consdata->minabsval;
2296 }
2297 
2298 /** calculates minimum and maximum local and global activity for constraint from scratch;
2299  * additionally recalculates maximum absolute value of coefficients
2300  */
2301 static
2303  SCIP* scip, /**< SCIP data structure */
2304  SCIP_CONSDATA* consdata /**< linear constraint data */
2305  )
2306 {
2307  int i;
2308 
2309  assert(scip != NULL);
2310  assert(consdata != NULL);
2311  assert(!consdata->validactivities);
2312  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2313  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2314  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2315  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2316 
2317  consdata->validmaxabsval = TRUE;
2318  consdata->validminabsval = TRUE;
2319  consdata->validactivities = TRUE;
2320  consdata->validminact = TRUE;
2321  consdata->validmaxact = TRUE;
2322  consdata->validglbminact = TRUE;
2323  consdata->validglbmaxact = TRUE;
2324  consdata->maxabsval = 0.0;
2325  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2326  consdata->minactivity = 0.0;
2327  consdata->maxactivity = 0.0;
2328  consdata->lastminactivity = 0.0;
2329  consdata->lastmaxactivity = 0.0;
2330  consdata->minactivityneginf = 0;
2331  consdata->minactivityposinf = 0;
2332  consdata->maxactivityneginf = 0;
2333  consdata->maxactivityposinf = 0;
2334  consdata->minactivityneghuge = 0;
2335  consdata->minactivityposhuge = 0;
2336  consdata->maxactivityneghuge = 0;
2337  consdata->maxactivityposhuge = 0;
2338  consdata->glbminactivity = 0.0;
2339  consdata->glbmaxactivity = 0.0;
2340  consdata->lastglbminactivity = 0.0;
2341  consdata->lastglbmaxactivity = 0.0;
2342  consdata->glbminactivityneginf = 0;
2343  consdata->glbminactivityposinf = 0;
2344  consdata->glbmaxactivityneginf = 0;
2345  consdata->glbmaxactivityposinf = 0;
2346  consdata->glbminactivityneghuge = 0;
2347  consdata->glbminactivityposhuge = 0;
2348  consdata->glbmaxactivityneghuge = 0;
2349  consdata->glbmaxactivityposhuge = 0;
2350 
2351  for( i = 0; i < consdata->nvars; ++i )
2352  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2353 
2354  consdata->lastminactivity = consdata->minactivity;
2355  consdata->lastmaxactivity = consdata->maxactivity;
2356  consdata->lastglbminactivity = consdata->glbminactivity;
2357  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2358 }
2359 
2360 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2361  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2362  */
2363 static
2364 void getMinActivity(
2365  SCIP* scip, /**< SCIP data structure */
2366  SCIP_CONSDATA* consdata, /**< linear constraint */
2367  int posinf, /**< number of coefficients contributing pos. infinite value */
2368  int neginf, /**< number of coefficients contributing neg. infinite value */
2369  int poshuge, /**< number of coefficients contributing huge pos. value */
2370  int neghuge, /**< number of coefficients contributing huge neg. value */
2371  SCIP_Real delta, /**< value to subtract from stored minactivity
2372  * (contribution of the variable set to zero when getting residual activity) */
2373  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2374  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2375  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2376  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2377  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2378  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2379  )
2380 {
2381  assert(scip != NULL);
2382  assert(consdata != NULL);
2383  assert(posinf >= 0);
2384  assert(neginf >= 0);
2385  assert(poshuge >= 0);
2386  assert(neghuge >= 0);
2387  assert(minactivity != NULL);
2388  assert(isrelax != NULL);
2389  assert(issettoinfinity != NULL);
2390 
2391  /* if we have pos. infinite contributions, the minactivity is +infty */
2392  if( posinf > 0 )
2393  {
2394  *minactivity = SCIPinfinity(scip);
2395  *issettoinfinity = TRUE;
2396  *isrelax = FALSE;
2397  }
2398  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2399  else if( neginf > 0 )
2400  {
2401  *minactivity = -SCIPinfinity(scip);
2402  *issettoinfinity = TRUE;
2403  *isrelax = FALSE;
2404  }
2405  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2406  else if( neghuge > 0 )
2407  {
2408  *minactivity = -SCIPinfinity(scip);
2409  *issettoinfinity = TRUE;
2410  *isrelax = TRUE;
2411  }
2412  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2413  else if( !goodrelax && poshuge > 0 )
2414  {
2415  *minactivity = -SCIPinfinity(scip);
2416  *issettoinfinity = TRUE;
2417  *isrelax = TRUE;
2418  }
2419  else
2420  {
2421  SCIP_Real tmpactivity;
2422 
2423  /* recompute minactivity if it is not valid */
2424  if( global )
2425  {
2426  if( !consdata->validglbminact )
2427  consdataRecomputeGlbMinactivity(scip, consdata);
2428  assert(consdata->validglbminact);
2429 
2430  tmpactivity = consdata->glbminactivity;
2431  }
2432  else
2433  {
2434  if( !consdata->validminact )
2435  consdataRecomputeMinactivity(scip, consdata);
2436  assert(consdata->validminact);
2437 
2438  tmpactivity = consdata->minactivity;
2439  }
2440 
2441  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2442  * a feasible relaxation of the minactivity is the number of positive huge contributions
2443  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2444  */
2445  if( poshuge > 0 )
2446  {
2447  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2448  *issettoinfinity = FALSE;
2449  *isrelax = TRUE;
2450  }
2451  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2452  else
2453  {
2454  *minactivity = tmpactivity - delta;
2455  *issettoinfinity = FALSE;
2456  *isrelax = FALSE;
2457  }
2458  }
2459 }
2460 
2461 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2462  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2463  */
2464 static
2465 void getMaxActivity(
2466  SCIP* scip, /**< SCIP data structure */
2467  SCIP_CONSDATA* consdata, /**< linear constraint */
2468  int posinf, /**< number of coefficients contributing pos. infinite value */
2469  int neginf, /**< number of coefficients contributing neg. infinite value */
2470  int poshuge, /**< number of coefficients contributing huge pos. value */
2471  int neghuge, /**< number of coefficients contributing huge neg. value */
2472  SCIP_Real delta, /**< value to subtract from stored maxactivity
2473  * (contribution of the variable set to zero when getting residual activity) */
2474  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2475  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2476  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2477  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2478  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2479  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2480  )
2481 {
2482  assert(scip != NULL);
2483  assert(consdata != NULL);
2484  assert(posinf >= 0);
2485  assert(neginf >= 0);
2486  assert(poshuge >= 0);
2487  assert(neghuge >= 0);
2488  assert(maxactivity != NULL);
2489  assert(isrelax != NULL);
2490  assert(issettoinfinity != NULL);
2491 
2492  /* if we have neg. infinite contributions, the maxactivity is -infty */
2493  if( neginf > 0 )
2494  {
2495  *maxactivity = -SCIPinfinity(scip);
2496  *issettoinfinity = TRUE;
2497  *isrelax = FALSE;
2498  }
2499  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2500  else if( posinf > 0 )
2501  {
2502  *maxactivity = SCIPinfinity(scip);
2503  *issettoinfinity = TRUE;
2504  *isrelax = FALSE;
2505  }
2506  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2507  else if( poshuge > 0 )
2508  {
2509  *maxactivity = SCIPinfinity(scip);
2510  *issettoinfinity = TRUE;
2511  *isrelax = TRUE;
2512  }
2513  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2514  else if( !goodrelax && neghuge > 0 )
2515  {
2516  *maxactivity = SCIPinfinity(scip);
2517  *issettoinfinity = TRUE;
2518  *isrelax = TRUE;
2519  }
2520  else
2521  {
2522  SCIP_Real tmpactivity;
2523 
2524  /* recompute maxactivity if it is not valid */
2525  if( global )
2526  {
2527  if( !consdata->validglbmaxact )
2528  consdataRecomputeGlbMaxactivity(scip, consdata);
2529  assert(consdata->validglbmaxact);
2530 
2531  tmpactivity = consdata->glbmaxactivity;
2532  }
2533  else
2534  {
2535  if( !consdata->validmaxact )
2536  consdataRecomputeMaxactivity(scip, consdata);
2537  assert(consdata->validmaxact);
2538 
2539  tmpactivity = consdata->maxactivity;
2540  }
2541 
2542  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2543  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2544  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2545  */
2546  if( neghuge > 0 )
2547  {
2548  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2549  *issettoinfinity = FALSE;
2550  *isrelax = TRUE;
2551  }
2552  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2553  else
2554  {
2555  *maxactivity = tmpactivity - delta;
2556  *issettoinfinity = FALSE;
2557  *isrelax = FALSE;
2558  }
2559  }
2560 }
2561 
2562 /** gets activity bounds for constraint */
2563 static
2565  SCIP* scip, /**< SCIP data structure */
2566  SCIP_CONSDATA* consdata, /**< linear constraint */
2567  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2568  * relaxed acticities ignored, anyway? */
2569  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2570  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2571  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2572  * i.e. <= the exact minactivity (in case of huge contributions),
2573  * or equal to the exact minimal activity */
2574  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2575  * i.e. >= the exact maxactivity (in case of huge contributions),
2576  * or equal to the exact maximal activity */
2577  )
2578 {
2579  SCIP_Bool issettoinfinity;
2580 
2581  assert(scip != NULL);
2582  assert(consdata != NULL);
2583  assert(minactivity != NULL);
2584  assert(maxactivity != NULL);
2585 
2586  if( !consdata->validactivities )
2587  {
2588  consdataCalcActivities(scip, consdata);
2589  assert(consdata->validminact);
2590  assert(consdata->validmaxact);
2591  }
2592  assert(consdata->minactivity < SCIP_INVALID);
2593  assert(consdata->maxactivity < SCIP_INVALID);
2594  assert(consdata->minactivityneginf >= 0);
2595  assert(consdata->minactivityposinf >= 0);
2596  assert(consdata->maxactivityneginf >= 0);
2597  assert(consdata->maxactivityposinf >= 0);
2598 
2599  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2600  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2601  minactivity, minisrelax, &issettoinfinity);
2602 
2603  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2604  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2605  maxactivity, maxisrelax, &issettoinfinity);
2606 }
2607 
2608 /** calculates activity bounds for constraint after setting variable to zero */
2609 static
2611  SCIP* scip, /**< SCIP data structure */
2612  SCIP_CONSDATA* consdata, /**< linear constraint */
2613  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2614  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2615  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2616  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2617  )
2618 {
2619  SCIP_VAR* var;
2620  SCIP_Real val;
2621  SCIP_Real lb;
2622  SCIP_Real ub;
2623  int v;
2624 
2625  assert(scip != NULL);
2626  assert(consdata != NULL);
2627  assert(cancelvar != NULL);
2628  assert(resactivity != NULL);
2629 
2630  *resactivity = 0.0;
2631 
2632  for( v = 0; v < consdata->nvars; ++v )
2633  {
2634  var = consdata->vars[v];
2635  assert(var != NULL);
2636  if( var == cancelvar )
2637  continue;
2638 
2639  val = consdata->vals[v];
2640 
2641  if( useglobalbounds )
2642  {
2643  lb = SCIPvarGetLbGlobal(var);
2644  ub = SCIPvarGetUbGlobal(var);
2645  }
2646  else
2647  {
2648  lb = SCIPvarGetLbLocal(var);
2649  ub = SCIPvarGetUbLocal(var);
2650  }
2651 
2652  assert(!SCIPisZero(scip, val));
2653  assert(SCIPisLE(scip, lb, ub));
2654 
2655  if( val > 0.0 )
2656  {
2657  if( isminresact )
2658  {
2659  assert(!SCIPisInfinity(scip, -lb));
2660  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2661  *resactivity += val*lb;
2662  }
2663  else
2664  {
2665  assert(!SCIPisInfinity(scip, ub));
2666  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2667  *resactivity += val*ub;
2668  }
2669  }
2670  else
2671  {
2672  if( isminresact)
2673  {
2674  assert(!SCIPisInfinity(scip, ub));
2675  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2676  *resactivity += val*ub;
2677  }
2678  else
2679  {
2680  assert(!SCIPisInfinity(scip, -lb));
2681  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2682  *resactivity += val*lb;
2683  }
2684  }
2685  }
2686  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2687 }
2688 
2689 /** gets activity bounds for constraint after setting variable to zero */
2690 static
2692  SCIP* scip, /**< SCIP data structure */
2693  SCIP_CONSDATA* consdata, /**< linear constraint */
2694  SCIP_VAR* var, /**< variable to calculate activity residual for */
2695  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2696  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2697  * relaxed acticities ignored, anyway? */
2698  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2699  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2700  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2701  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2702  * contributions), or equal to the exact residual minactivity */
2703  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2704  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2705  * contributions), or equal to the exact residual minactivity */
2706  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2707  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2708  )
2709 {
2710  SCIP_Real minactbound;
2711  SCIP_Real maxactbound;
2712  SCIP_Real absval;
2713 
2714  assert(scip != NULL);
2715  assert(consdata != NULL);
2716  assert(var != NULL);
2717  assert(minresactivity != NULL);
2718  assert(maxresactivity != NULL);
2719  assert(minisrelax != NULL);
2720  assert(maxisrelax != NULL);
2721  assert(isminsettoinfinity != NULL);
2722  assert(ismaxsettoinfinity != NULL);
2723 
2724  /* get activity bounds of linear constraint */
2725  if( !consdata->validactivities )
2726  {
2727  consdataCalcActivities(scip, consdata);
2728  assert(consdata->validminact);
2729  assert(consdata->validmaxact);
2730  }
2731  assert(consdata->minactivity < SCIP_INVALID);
2732  assert(consdata->maxactivity < SCIP_INVALID);
2733  assert(consdata->minactivityneginf >= 0);
2734  assert(consdata->minactivityposinf >= 0);
2735  assert(consdata->maxactivityneginf >= 0);
2736  assert(consdata->maxactivityposinf >= 0);
2737  assert(consdata->minactivityneghuge >= 0);
2738  assert(consdata->minactivityposhuge >= 0);
2739  assert(consdata->maxactivityneghuge >= 0);
2740  assert(consdata->maxactivityposhuge >= 0);
2741 
2742  if( val > 0.0 )
2743  {
2744  minactbound = SCIPvarGetLbLocal(var);
2745  maxactbound = SCIPvarGetUbLocal(var);
2746  absval = val;
2747  }
2748  else
2749  {
2750  minactbound = -SCIPvarGetUbLocal(var);
2751  maxactbound = -SCIPvarGetLbLocal(var);
2752  absval = -val;
2753  }
2754 
2755  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2756  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2757  */
2758  if( SCIPisInfinity(scip, minactbound) )
2759  {
2760  assert(consdata->minactivityposinf >= 1);
2761 
2762  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2763  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2764  minresactivity, minisrelax, isminsettoinfinity);
2765  }
2766  else if( SCIPisInfinity(scip, -minactbound) )
2767  {
2768  assert(consdata->minactivityneginf >= 1);
2769 
2770  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2771  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2772  minresactivity, minisrelax, isminsettoinfinity);
2773  }
2774  else if( SCIPisHugeValue(scip, minactbound * absval) )
2775  {
2776  assert(consdata->minactivityposhuge >= 1);
2777 
2778  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2779  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2780  minresactivity, minisrelax, isminsettoinfinity);
2781  }
2782  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2783  {
2784  assert(consdata->minactivityneghuge >= 1);
2785 
2786  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2787  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2788  minresactivity, minisrelax, isminsettoinfinity);
2789  }
2790  else
2791  {
2792  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2793  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2794  minresactivity, minisrelax, isminsettoinfinity);
2795  }
2796 
2797  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2798  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2799  */
2800  if( SCIPisInfinity(scip, -maxactbound) )
2801  {
2802  assert(consdata->maxactivityneginf >= 1);
2803 
2804  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2805  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2806  maxresactivity, maxisrelax, ismaxsettoinfinity);
2807  }
2808  else if( SCIPisInfinity(scip, maxactbound) )
2809  {
2810  assert(consdata->maxactivityposinf >= 1);
2811 
2812  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2813  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2814  maxresactivity, maxisrelax, ismaxsettoinfinity);
2815  }
2816  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2817  {
2818  assert(consdata->maxactivityposhuge >= 1);
2819 
2820  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2821  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2822  maxresactivity, maxisrelax, ismaxsettoinfinity);
2823  }
2824  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2825  {
2826  assert(consdata->maxactivityneghuge >= 1);
2827 
2828  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2829  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2830  maxresactivity, maxisrelax, ismaxsettoinfinity);
2831  }
2832  else
2833  {
2834  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2835  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2836  maxresactivity, maxisrelax, ismaxsettoinfinity);
2837  }
2838 }
2839 
2840 /** gets global activity bounds for constraint */
2841 static
2843  SCIP* scip, /**< SCIP data structure */
2844  SCIP_CONSDATA* consdata, /**< linear constraint */
2845  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2846  * relaxed acticities ignored, anyway? */
2847  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2848  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2849  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2850  * i.e. <= the exact minactivity (in case of huge contributions),
2851  * or equal to the exact minimal activity */
2852  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2853  * i.e. >= the exact maxactivity (in case of huge contributions),
2854  * or equal to the exact maximal activity */
2855  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2856  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2857  )
2858 {
2859  assert(scip != NULL);
2860  assert(consdata != NULL);
2861  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2862  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2863 
2864  if( !consdata->validactivities )
2865  {
2866  consdataCalcActivities(scip, consdata);
2867  assert(consdata->validglbminact);
2868  assert(consdata->validglbmaxact);
2869  }
2870  assert(consdata->glbminactivity < SCIP_INVALID);
2871  assert(consdata->glbmaxactivity < SCIP_INVALID);
2872  assert(consdata->glbminactivityneginf >= 0);
2873  assert(consdata->glbminactivityposinf >= 0);
2874  assert(consdata->glbmaxactivityneginf >= 0);
2875  assert(consdata->glbmaxactivityposinf >= 0);
2876  assert(consdata->glbminactivityneghuge >= 0);
2877  assert(consdata->glbminactivityposhuge >= 0);
2878  assert(consdata->glbmaxactivityneghuge >= 0);
2879  assert(consdata->glbmaxactivityposhuge >= 0);
2880 
2881  if( glbminactivity != NULL )
2882  {
2883  assert(isminsettoinfinity != NULL);
2884  assert(minisrelax != NULL);
2885 
2886  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2887  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2888  glbminactivity, minisrelax, isminsettoinfinity);
2889  }
2890 
2891  if( glbmaxactivity != NULL )
2892  {
2893  assert(ismaxsettoinfinity != NULL);
2894  assert(maxisrelax != NULL);
2895 
2896  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2897  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2898  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2899  }
2900 }
2901 
2902 /** gets global activity bounds for constraint after setting variable to zero */
2903 static
2905  SCIP* scip, /**< SCIP data structure */
2906  SCIP_CONSDATA* consdata, /**< linear constraint */
2907  SCIP_VAR* var, /**< variable to calculate activity residual for */
2908  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2909  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2910  * relaxed acticities ignored, anyway? */
2911  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2912  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2913  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2914  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2915  * contributions), or equal to the exact residual minactivity */
2916  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2917  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2918  * contributions), or equal to the exact residual minactivity */
2919  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2920  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2921  )
2922 {
2923  SCIP_Real minactbound;
2924  SCIP_Real maxactbound;
2925  SCIP_Real absval;
2926 
2927  assert(scip != NULL);
2928  assert(consdata != NULL);
2929  assert(var != NULL);
2930  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2931  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2932 
2933  /* get activity bounds of linear constraint */
2934  if( !consdata->validactivities )
2935  consdataCalcActivities(scip, consdata);
2936 
2937  assert(consdata->glbminactivity < SCIP_INVALID);
2938  assert(consdata->glbmaxactivity < SCIP_INVALID);
2939  assert(consdata->glbminactivityneginf >= 0);
2940  assert(consdata->glbminactivityposinf >= 0);
2941  assert(consdata->glbmaxactivityneginf >= 0);
2942  assert(consdata->glbmaxactivityposinf >= 0);
2943 
2944  if( val > 0.0 )
2945  {
2946  minactbound = SCIPvarGetLbGlobal(var);
2947  maxactbound = SCIPvarGetUbGlobal(var);
2948  absval = val;
2949  }
2950  else
2951  {
2952  minactbound = -SCIPvarGetUbGlobal(var);
2953  maxactbound = -SCIPvarGetLbGlobal(var);
2954  absval = -val;
2955  }
2956 
2957  if( minresactivity != NULL )
2958  {
2959  assert(isminsettoinfinity != NULL);
2960  assert(minisrelax != NULL);
2961 
2962  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2963  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2964  */
2965  if( SCIPisInfinity(scip, minactbound) )
2966  {
2967  assert(consdata->glbminactivityposinf >= 1);
2968 
2969  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2970  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2971  minresactivity, minisrelax, isminsettoinfinity);
2972  }
2973  else if( SCIPisInfinity(scip, -minactbound) )
2974  {
2975  assert(consdata->glbminactivityneginf >= 1);
2976 
2977  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2978  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2979  minresactivity, minisrelax, isminsettoinfinity);
2980  }
2981  else if( SCIPisHugeValue(scip, minactbound * absval) )
2982  {
2983  assert(consdata->glbminactivityposhuge >= 1);
2984 
2985  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2986  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2987  minresactivity, minisrelax, isminsettoinfinity);
2988  }
2989  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2990  {
2991  assert(consdata->glbminactivityneghuge >= 1);
2992 
2993  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2994  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2995  minresactivity, minisrelax, isminsettoinfinity);
2996  }
2997  else
2998  {
2999  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3000  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3001  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3002  }
3003  }
3004 
3005  if( maxresactivity != NULL )
3006  {
3007  assert(ismaxsettoinfinity != NULL);
3008  assert(maxisrelax != NULL);
3009 
3010  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3011  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3012  */
3013  if( SCIPisInfinity(scip, -maxactbound) )
3014  {
3015  assert(consdata->glbmaxactivityneginf >= 1);
3016 
3017  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3018  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3019  maxresactivity, maxisrelax, ismaxsettoinfinity);
3020  }
3021  else if( SCIPisInfinity(scip, maxactbound) )
3022  {
3023  assert(consdata->glbmaxactivityposinf >= 1);
3024 
3025  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3026  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3027  maxresactivity, maxisrelax, ismaxsettoinfinity);
3028  }
3029  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3030  {
3031  assert(consdata->glbmaxactivityposhuge >= 1);
3032 
3033  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3034  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3035  maxresactivity, maxisrelax, ismaxsettoinfinity);
3036  }
3037  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3038  {
3039  assert(consdata->glbmaxactivityneghuge >= 1);
3040 
3041  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3042  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3043  maxresactivity, maxisrelax, ismaxsettoinfinity);
3044  }
3045  else
3046  {
3047  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3048  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3049  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3050  }
3051  }
3052 }
3053 
3054 /** calculates the activity of the linear constraint for given solution */
3055 static
3057  SCIP* scip, /**< SCIP data structure */
3058  SCIP_CONSDATA* consdata, /**< linear constraint data */
3059  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3060  )
3061 {
3062  SCIP_Real activity;
3063 
3064  assert(scip != NULL);
3065  assert(consdata != NULL);
3066 
3067  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3068  activity = consdataComputePseudoActivity(scip, consdata);
3069  else
3070  {
3071  SCIP_Real solval;
3072  int nposinf;
3073  int nneginf;
3074  SCIP_Bool negsign;
3075  int v;
3076 
3077  activity = 0.0;
3078  nposinf = 0;
3079  nneginf = 0;
3080 
3081  for( v = 0; v < consdata->nvars; ++v )
3082  {
3083  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3084 
3085  if( consdata->vals[v] < 0 )
3086  negsign = TRUE;
3087  else
3088  negsign = FALSE;
3089 
3090  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3091  ++nposinf;
3092  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3093  ++nneginf;
3094  else
3095  activity += consdata->vals[v] * solval;
3096  }
3097  assert(nneginf >= 0 && nposinf >= 0);
3098 
3099  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3100 
3101  /* check for amount of infinity values and correct the activity */
3102  if( nposinf > 0 && nneginf > 0 )
3103  activity = (consdata->rhs + consdata->lhs) / 2;
3104  else if( nposinf > 0 )
3105  activity = SCIPinfinity(scip);
3106  else if( nneginf > 0 )
3107  activity = -SCIPinfinity(scip);
3108 
3109  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3110  }
3111 
3112  if( activity == SCIP_INVALID ) /*lint !e777*/
3113  return activity;
3114  else if( activity < 0 )
3115  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3116  else
3117  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3118 
3119  return activity;
3120 }
3121 
3122 /** calculates the feasibility of the linear constraint for given solution */
3123 static
3125  SCIP* scip, /**< SCIP data structure */
3126  SCIP_CONSDATA* consdata, /**< linear constraint data */
3127  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3128  )
3129 {
3130  SCIP_Real activity;
3131 
3132  assert(scip != NULL);
3133  assert(consdata != NULL);
3134 
3135  activity = consdataGetActivity(scip, consdata, sol);
3136 
3137  if( activity == SCIP_INVALID ) /*lint !e777*/
3138  return -SCIPinfinity(scip);
3139 
3140  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3142 
3143 /** updates bit signatures after adding a single coefficient */
3144 static
3146  SCIP_CONSDATA* consdata, /**< linear constraint data */
3147  int pos /**< position of coefficient to update signatures for */
3148  )
3149 {
3150  uint64_t varsignature;
3151  SCIP_Real lb;
3152  SCIP_Real ub;
3153  SCIP_Real val;
3154 
3155  assert(consdata != NULL);
3156  assert(consdata->validsignature);
3157 
3158  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3159  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3160  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3161  val = consdata->vals[pos];
3162  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3163  consdata->possignature |= varsignature;
3164  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3165  consdata->negsignature |= varsignature;
3166 }
3167 
3168 /** calculates the bit signatures of the given constraint data */
3169 static
3171  SCIP_CONSDATA* consdata /**< linear constraint data */
3172  )
3173 {
3174  assert(consdata != NULL);
3175 
3176  if( !consdata->validsignature )
3177  {
3178  int i;
3179 
3180  consdata->validsignature = TRUE;
3181  consdata->possignature = 0;
3182  consdata->negsignature = 0;
3183  for( i = 0; i < consdata->nvars; ++i )
3184  consdataUpdateSignatures(consdata, i);
3185  }
3186 }
3188 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3189 static
3190 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3191 { /*lint --e{715}*/
3192  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3193 
3194  assert(consdata != NULL);
3195  assert(0 <= ind1 && ind1 < consdata->nvars);
3196  assert(0 <= ind2 && ind2 < consdata->nvars);
3197 
3198  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3199 }
3200 
3201 /** permutes the constraint's variables according to a given permutation. */
3202 static
3203 void permSortConsdata(
3204  SCIP_CONSDATA* consdata, /**< the constraint data */
3205  int* perm, /**< the target permutation */
3206  int nvars /**< the number of variables */
3207  )
3208 { /*lint --e{715}*/
3209  SCIP_VAR* varv;
3210  SCIP_EVENTDATA* eventdatav;
3211  SCIP_Real valv;
3212  int v;
3213  int i;
3214  int nexti;
3215 
3216  assert(perm != NULL);
3217  assert(consdata != NULL);
3218 
3219  /* permute the variables in the linear constraint according to the target permutation */
3220  eventdatav = NULL;
3221  for( v = 0; v < nvars; ++v )
3222  {
3223  if( perm[v] != v )
3224  {
3225  varv = consdata->vars[v];
3226  valv = consdata->vals[v];
3227  if( consdata->eventdata != NULL )
3228  eventdatav = consdata->eventdata[v];
3229  i = v;
3230  do
3231  {
3232  assert(0 <= perm[i] && perm[i] < nvars);
3233  assert(perm[i] != i);
3234  consdata->vars[i] = consdata->vars[perm[i]];
3235  consdata->vals[i] = consdata->vals[perm[i]];
3236  if( consdata->eventdata != NULL )
3237  {
3238  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3239  consdata->eventdata[i]->varpos = i;
3240  }
3241  nexti = perm[i];
3242  perm[i] = i;
3243  i = nexti;
3244  }
3245  while( perm[i] != v );
3246  consdata->vars[i] = varv;
3247  consdata->vals[i] = valv;
3248  if( consdata->eventdata != NULL )
3249  {
3250  consdata->eventdata[i] = eventdatav;
3251  consdata->eventdata[i]->varpos = i;
3252  }
3253  perm[i] = i;
3254  }
3255  }
3256 #ifdef SCIP_DEBUG
3257  /* check sorting */
3258  for( v = 0; v < nvars; ++v )
3259  {
3260  assert(perm[v] == v);
3261  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3262  }
3263 #endif
3264 }
3265 
3266 /** sorts linear constraint's variables depending on the stage of the solving process:
3267  * - during PRESOLVING
3268  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3269  * and the variables of the same type by non-decreasing variable index
3270  *
3271  * - during SOLVING
3272  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3273  * This fastens the propagation time of the constraint handler.
3274  */
3275 static
3277  SCIP* scip, /**< SCIP data structure */
3278  SCIP_CONSDATA* consdata /**< linear constraint data */
3279  )
3280 {
3281  assert(scip != NULL);
3282  assert(consdata != NULL);
3283 
3284  /* check if there are variables for sorting */
3285  if( consdata->nvars <= 1 )
3286  {
3287  consdata->sorted = TRUE;
3288  consdata->binvarssorted = TRUE;
3289  }
3290  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3291  {
3292  int* perm;
3294  /* get temporary memory to store the sorted permutation */
3295  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3296 
3297  /* call sorting method */
3298  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3299 
3300  permSortConsdata(consdata, perm, consdata->nvars);
3301 
3302  /* free temporary memory */
3303  SCIPfreeBufferArray(scip, &perm);
3304 
3305  consdata->sorted = TRUE;
3306  consdata->binvarssorted = FALSE;
3307  }
3308  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3309  {
3310  SCIP_EVENTDATA** eventdata;
3311  SCIP_VAR** vars;
3312  SCIP_Real* vals;
3313  int nvars;
3314  int v;
3315  int lastbin;
3316 
3317  nvars = consdata->nvars;
3318  vars = consdata->vars;
3319  vals = consdata->vals;
3320  eventdata = consdata->eventdata;
3321  assert(vars != NULL || nvars == 0);
3322  assert(vals != NULL || nvars == 0);
3323 
3324  lastbin = 0;
3325  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3326  for( v = 0; v < nvars; ++v )
3327  {
3328  assert( vars != NULL); /* for flexelint */
3329  assert( vals != NULL); /* for flexelint */
3330  if( SCIPvarIsBinary(vars[v]) )
3331  {
3332  /* swap variable at the end of the binary variables, if necessary */
3333  if( lastbin < v )
3334  {
3335  SCIP_VAR* tmpvar;
3336  SCIP_Real tmpval;
3337 
3338  tmpvar = vars[lastbin];
3339  tmpval = vals[lastbin];
3340 
3341  vars[lastbin] = vars[v];
3342  vals[lastbin] = vals[v];
3343 
3344  vars[v] = tmpvar;
3345  vals[v] = tmpval;
3346 
3347  if( eventdata != NULL )
3348  {
3349  SCIP_EVENTDATA* tmpeventdata;
3350 
3351  tmpeventdata = eventdata[lastbin];
3352  eventdata[lastbin] = eventdata[v];
3353  eventdata[lastbin]->varpos = lastbin;
3354  eventdata[v] = tmpeventdata;
3355  eventdata[v]->varpos = v;
3356  }
3357  assert(SCIPvarIsBinary(vars[lastbin]));
3358  }
3359 #ifndef NDEBUG
3360  else
3361  assert(lastbin == v);
3362 #endif
3363  ++lastbin;
3364  }
3365  }
3366  consdata->nbinvars = lastbin;
3367 
3368 #ifndef NDEBUG
3369  /* check sorting */
3370  for( v = 0; v < nvars; ++v )
3371  {
3372  assert(vars != NULL); /* for flexelint */
3373  assert(eventdata == NULL || eventdata[v]->varpos == v);
3374  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3375  }
3376 #endif
3377 
3378  if( consdata->nbinvars > 1 )
3379  {
3380  SCIP_Real* absvals;
3381  int* perm;
3382 
3383  assert(lastbin == consdata->nbinvars);
3384  assert(lastbin <= nvars);
3385  assert(vals != NULL);
3386 
3387  /* initialize absolute coefficients and the target permutation for binary variables */
3388  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3389  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3390 
3391  for( v = 0; v < lastbin; ++v )
3392  {
3393  absvals[v] = ABS(vals[v]);
3394  perm[v] = v;
3395  }
3396 
3397  /* execute the sorting */
3398  SCIPsortDownRealInt(absvals, perm, lastbin);
3399 
3400  permSortConsdata(consdata, perm, lastbin);
3401 
3402  /* free temporary arrays */
3403  SCIPfreeBufferArray(scip, &perm);
3404  SCIPfreeBufferArray(scip, &absvals);
3405  }
3406  consdata->binvarssorted = TRUE;
3407 
3408  /* presolve sorting cannot be guaranteed after binary sorting */
3409  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3410  }
3411  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3412  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3413 
3414  return SCIP_OKAY;
3415 }
3416 
3417 
3418 /*
3419  * local linear constraint handler methods
3420  */
3421 
3422 /** sets left hand side of linear constraint */
3423 static
3425  SCIP* scip, /**< SCIP data structure */
3426  SCIP_CONS* cons, /**< linear constraint */
3427  SCIP_Real lhs /**< new left hand side */
3428  )
3429 {
3430  SCIP_CONSDATA* consdata;
3431  SCIP_Bool locked;
3432  int i;
3433 
3434  assert(scip != NULL);
3435  assert(cons != NULL);
3436  assert(!SCIPisInfinity(scip, lhs));
3437 
3438  /* adjust value to not be smaller than -inf */
3439  if ( SCIPisInfinity(scip, -lhs) )
3440  lhs = -SCIPinfinity(scip);
3442  consdata = SCIPconsGetData(cons);
3443  assert(consdata != NULL);
3444  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3445  assert(!SCIPisInfinity(scip, consdata->lhs));
3446 
3447  /* check whether the side is not changed */
3448  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3449  return SCIP_OKAY;
3450 
3451  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3452  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3453  {
3454  consdata->rhs = lhs;
3455  assert(consdata->row == NULL);
3456  }
3457 
3458  locked = FALSE;
3459  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3460  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3461 
3462  /* if necessary, update the rounding locks of variables */
3463  if( locked )
3464  {
3465  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3466  {
3467  SCIP_VAR** vars;
3468  SCIP_Real* vals;
3469  int v;
3470 
3471  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3472  vars = consdata->vars;
3473  vals = consdata->vals;
3474 
3475  for( v = 0; v < consdata->nvars; ++v )
3476  {
3477  assert(vars[v] != NULL);
3478  assert(!SCIPisZero(scip, vals[v]));
3479 
3480  if( SCIPisPositive(scip, vals[v]) )
3481  {
3482  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3483  }
3484  else
3485  {
3486  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3487  }
3488  }
3489  }
3490  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3491  {
3492  SCIP_VAR** vars;
3493  SCIP_Real* vals;
3494  int v;
3495 
3496  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3497  vars = consdata->vars;
3498  vals = consdata->vals;
3499 
3500  for( v = 0; v < consdata->nvars; ++v )
3501  {
3502  assert(vars[v] != NULL);
3503  assert(!SCIPisZero(scip, vals[v]));
3504 
3505  if( SCIPisPositive(scip, vals[v]) )
3506  {
3507  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3508  }
3509  else
3510  {
3511  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3512  }
3513  }
3514  }
3515  }
3516 
3517  /* 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 */
3518  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3519  {
3520  consdata->boundstightened = 0;
3521  consdata->presolved = FALSE;
3522  consdata->cliquesadded = FALSE;
3523  consdata->implsadded = FALSE;
3524 
3525  /* mark the constraint for propagation */
3526  if( SCIPconsIsTransformed(cons) )
3527  {
3528  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3529  }
3530  }
3531 
3532  /* set new left hand side and update constraint data */
3533  consdata->lhs = lhs;
3534  consdata->changed = TRUE;
3535  consdata->normalized = FALSE;
3536  consdata->upgradetried = FALSE;
3537  consdata->rangedrowpropagated = 0;
3538 
3539  /* update the lhs of the LP row */
3540  if( consdata->row != NULL )
3541  {
3542  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3543  }
3544 
3545  return SCIP_OKAY;
3546 }
3547 
3548 /** sets right hand side of linear constraint */
3549 static
3551  SCIP* scip, /**< SCIP data structure */
3552  SCIP_CONS* cons, /**< linear constraint */
3553  SCIP_Real rhs /**< new right hand side */
3554  )
3555 {
3556  SCIP_CONSDATA* consdata;
3557  SCIP_Bool locked;
3558  int i;
3559 
3560  assert(scip != NULL);
3561  assert(cons != NULL);
3562  assert(!SCIPisInfinity(scip, -rhs));
3563 
3564  /* adjust value to not be larger than inf */
3565  if ( SCIPisInfinity(scip, rhs) )
3566  rhs = SCIPinfinity(scip);
3568  consdata = SCIPconsGetData(cons);
3569  assert(consdata != NULL);
3570  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3571  assert(!SCIPisInfinity(scip, -consdata->rhs));
3572 
3573  /* check whether the side is not changed */
3574  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3575  return SCIP_OKAY;
3576 
3577  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3578  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3579  {
3580  consdata->lhs = rhs;
3581  assert(consdata->row == NULL);
3582  }
3583 
3584  locked = FALSE;
3585  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3586  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3587 
3588  /* if necessary, update the rounding locks of variables */
3589  if( locked )
3590  {
3591  assert(SCIPconsIsTransformed(cons));
3592 
3593  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3594  {
3595  SCIP_VAR** vars;
3596  SCIP_Real* vals;
3597  int v;
3598 
3599  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3600  vars = consdata->vars;
3601  vals = consdata->vals;
3602 
3603  for( v = 0; v < consdata->nvars; ++v )
3604  {
3605  assert(vars[v] != NULL);
3606  assert(!SCIPisZero(scip, vals[v]));
3607 
3608  if( SCIPisPositive(scip, vals[v]) )
3609  {
3610  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3611  }
3612  else
3613  {
3614  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3615  }
3616  }
3617  }
3618  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3619  {
3620  SCIP_VAR** vars;
3621  SCIP_Real* vals;
3622  int v;
3623 
3624  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3625  vars = consdata->vars;
3626  vals = consdata->vals;
3627 
3628  for( v = 0; v < consdata->nvars; ++v )
3629  {
3630  assert(vars[v] != NULL);
3631  assert(!SCIPisZero(scip, vals[v]));
3632 
3633  if( SCIPisPositive(scip, vals[v]) )
3634  {
3635  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3636  }
3637  else
3638  {
3639  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3640  }
3641  }
3642  }
3643  }
3644 
3645  /* 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 */
3646  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3647  {
3648  consdata->boundstightened = 0;
3649  consdata->presolved = FALSE;
3650  consdata->cliquesadded = FALSE;
3651  consdata->implsadded = FALSE;
3652 
3653  /* mark the constraint for propagation */
3654  if( SCIPconsIsTransformed(cons) )
3655  {
3656  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3657  }
3658  }
3659 
3660  /* set new right hand side and update constraint data */
3661  consdata->rhs = rhs;
3662  consdata->changed = TRUE;
3663  consdata->normalized = FALSE;
3664  consdata->upgradetried = FALSE;
3665  consdata->rangedrowpropagated = 0;
3666 
3667  /* update the rhs of the LP row */
3668  if( consdata->row != NULL )
3669  {
3670  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3671  }
3672 
3673  return SCIP_OKAY;
3674 }
3675 
3676 /** adds coefficient in linear constraint */
3677 static
3679  SCIP* scip, /**< SCIP data structure */
3680  SCIP_CONS* cons, /**< linear constraint */
3681  SCIP_VAR* var, /**< variable of constraint entry */
3682  SCIP_Real val /**< coefficient of constraint entry */
3683  )
3684 {
3685  SCIP_CONSDATA* consdata;
3686  SCIP_Bool transformed;
3687 
3688  assert(scip != NULL);
3689  assert(cons != NULL);
3690  assert(var != NULL);
3691 
3692  /* ignore coefficient if it is nearly zero */
3693  if( SCIPisZero(scip, val) )
3694  return SCIP_OKAY;
3696  consdata = SCIPconsGetData(cons);
3697  assert(consdata != NULL);
3698 
3699  /* are we in the transformed problem? */
3700  transformed = SCIPconsIsTransformed(cons);
3701 
3702  /* always use transformed variables in transformed constraints */
3703  if( transformed )
3704  {
3705  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3706  }
3707  assert(var != NULL);
3708  assert(transformed == SCIPvarIsTransformed(var));
3709 
3710  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3711  consdata->vars[consdata->nvars] = var;
3712  consdata->vals[consdata->nvars] = val;
3713  consdata->nvars++;
3714 
3715  /* capture variable */
3716  SCIP_CALL( SCIPcaptureVar(scip, var) );
3717 
3718  /* if we are in transformed problem, the variable needs an additional event data */
3719  if( transformed )
3720  {
3721  if( consdata->eventdata != NULL )
3722  {
3723  SCIP_CONSHDLR* conshdlr;
3724  SCIP_CONSHDLRDATA* conshdlrdata;
3725 
3726  /* check for event handler */
3727  conshdlr = SCIPconsGetHdlr(cons);
3728  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3729  assert(conshdlrdata != NULL);
3730  assert(conshdlrdata->eventhdlr != NULL);
3731 
3732  /* initialize eventdata array */
3733  consdata->eventdata[consdata->nvars-1] = NULL;
3734 
3735  /* catch bound change events of variable */
3736  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3737  }
3738 
3739  /* update minimum and maximum activities */
3740  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3741 
3742  /* update maximum activity delta */
3743  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3744  {
3745  SCIP_Real lb;
3746  SCIP_Real ub;
3747 
3748  lb = SCIPvarGetLbLocal(var);
3749  ub = SCIPvarGetUbLocal(var);
3750 
3751  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3752  {
3753  consdata->maxactdelta = SCIPinfinity(scip);
3754  consdata->maxactdeltavar = var;
3755  }
3756  else
3757  {
3758  SCIP_Real domain = ub - lb;
3759  SCIP_Real delta = REALABS(val) * domain;
3760 
3761  if( delta > consdata->maxactdelta )
3762  {
3763  consdata->maxactdelta = delta;
3764  consdata->maxactdeltavar = var;
3765  }
3766  }
3767  }
3768  }
3769 
3770  /* install rounding locks for new variable */
3771  SCIP_CALL( lockRounding(scip, cons, var, val) );
3772 
3773  /* mark the constraint for propagation */
3774  if( transformed )
3775  {
3776  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3777  }
3778 
3779  consdata->boundstightened = 0;
3780  consdata->presolved = FALSE;
3781  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3782 
3783  if( consdata->validsignature )
3784  consdataUpdateSignatures(consdata, consdata->nvars-1);
3785 
3786  consdata->changed = TRUE;
3787  consdata->normalized = FALSE;
3788  consdata->upgradetried = FALSE;
3789  consdata->cliquesadded = FALSE;
3790  consdata->implsadded = FALSE;
3791  consdata->rangedrowpropagated = 0;
3792 
3793  if( consdata->nvars == 1 )
3794  {
3795  consdata->binvarssorted = TRUE;
3796  consdata->sorted = TRUE;
3797  consdata->merged = TRUE;
3798  }
3799  else
3800  {
3801  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3802  consdata->sorted = consdata->sorted
3803  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3804  consdata->merged = FALSE;
3805  }
3806 
3807  /* update hascontvar and hasnonbinvar flags */
3808  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3809  {
3810  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3811 
3812  if( vartype != SCIP_VARTYPE_BINARY )
3813  {
3814  consdata->hasnonbinvar = TRUE;
3815 
3816  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3817  consdata->hascontvar = TRUE;
3818  }
3819  }
3820 
3821  /* add the new coefficient to the LP row */
3822  if( consdata->row != NULL )
3823  {
3824  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3825  }
3826 
3827  return SCIP_OKAY;
3828 }
3829 
3830 /** deletes coefficient at given position from linear constraint data */
3831 static
3833  SCIP* scip, /**< SCIP data structure */
3834  SCIP_CONS* cons, /**< linear constraint */
3835  int pos /**< position of coefficient to delete */
3836  )
3837 {
3838  SCIP_CONSDATA* consdata;
3839  SCIP_VAR* var;
3840  SCIP_Real val;
3841 
3842  assert(scip != NULL);
3843  assert(cons != NULL);
3844 
3845  consdata = SCIPconsGetData(cons);
3846  assert(consdata != NULL);
3847  assert(0 <= pos && pos < consdata->nvars);
3848 
3849  var = consdata->vars[pos];
3850  val = consdata->vals[pos];
3851  assert(var != NULL);
3852 
3853  /* remove rounding locks for deleted variable */
3854  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3855 
3856  /* if we are in transformed problem, delete the event data of the variable */
3857  if( SCIPconsIsTransformed(cons) )
3858  {
3859  SCIP_CONSHDLR* conshdlr;
3860  SCIP_CONSHDLRDATA* conshdlrdata;
3861 
3862  /* check for event handler */
3863  conshdlr = SCIPconsGetHdlr(cons);
3864  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3865  assert(conshdlrdata != NULL);
3866  assert(conshdlrdata->eventhdlr != NULL);
3867 
3868  /* drop bound change events of variable */
3869  if( consdata->eventdata != NULL )
3870  {
3871  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3872  assert(consdata->eventdata[pos] == NULL);
3873  }
3874  }
3875 
3876  /* move the last variable to the free slot */
3877  if( pos != consdata->nvars-1 )
3878  {
3879  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3880 
3881  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3882  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3883 
3884  if( consdata->eventdata != NULL )
3885  {
3886  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3887  assert(consdata->eventdata[pos] != NULL);
3888  consdata->eventdata[pos]->varpos = pos;
3889  }
3890  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3891  }
3892  consdata->nvars--;
3893 
3894  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3895  * of the remaining variable, or give exactly 0.0)
3896  */
3897  if( consdata->nvars <= 1 )
3898  consdataInvalidateActivities(consdata);
3899  else
3900  {
3901  if( SCIPconsIsTransformed(cons) )
3902  {
3903  /* if we are in transformed problem, update minimum and maximum activities */
3904  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3905 
3906  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3907  * delta needs to be recalculated on the next real propagation
3908  */
3909  if( consdata->maxactdeltavar == var )
3910  {
3911  consdata->maxactdelta = SCIP_INVALID;
3912  consdata->maxactdeltavar = NULL;
3913  }
3914  }
3915  }
3916 
3917  /* mark the constraint for propagation */
3918  if( SCIPconsIsTransformed(cons) )
3919  {
3920  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3921  }
3922 
3923  consdata->boundstightened = 0;
3924  consdata->presolved = FALSE;
3925  consdata->validsignature = FALSE;
3926  consdata->changed = TRUE;
3927  consdata->normalized = FALSE;
3928  consdata->upgradetried = FALSE;
3929  consdata->cliquesadded = FALSE;
3930  consdata->implsadded = FALSE;
3931  consdata->rangedrowpropagated = 0;
3932 
3933  /* check if hasnonbinvar flag might be incorrect now */
3934  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3935  {
3936  consdata->hasnonbinvalid = FALSE;
3937  }
3938 
3939  /* delete coefficient from the LP row */
3940  if( consdata->row != NULL )
3941  {
3942  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3943  }
3944 
3945  /* release variable */
3946  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3947 
3948  return SCIP_OKAY;
3949 }
3950 
3951 /** changes coefficient value at given position of linear constraint data */
3952 static
3954  SCIP* scip, /**< SCIP data structure */
3955  SCIP_CONS* cons, /**< linear constraint */
3956  int pos, /**< position of coefficient to delete */
3957  SCIP_Real newval /**< new value of coefficient */
3958  )
3959 {
3960  SCIP_CONSDATA* consdata;
3961  SCIP_VAR* var;
3962  SCIP_Real val;
3963  SCIP_Bool locked;
3964  int i;
3965 
3966  assert(scip != NULL);
3967  assert(cons != NULL);
3968  assert(!SCIPisZero(scip, newval));
3969 
3970  consdata = SCIPconsGetData(cons);
3971  assert(consdata != NULL);
3972  assert(0 <= pos && pos < consdata->nvars);
3973  assert(!SCIPisZero(scip, newval));
3974 
3975  var = consdata->vars[pos];
3976  val = consdata->vals[pos];
3977  assert(var != NULL);
3978  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3979 
3980  locked = FALSE;
3981  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3982  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3983 
3984  /* if necessary, update the rounding locks of the variable */
3985  if( locked && newval * val < 0.0 )
3986  {
3987  assert(SCIPconsIsTransformed(cons));
3988 
3989  /* remove rounding locks for variable with old coefficient */
3990  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3991 
3992  /* install rounding locks for variable with new coefficient */
3993  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3994  }
3995 
3996  /* change the value */
3997  consdata->vals[pos] = newval;
3998 
3999  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
4000 
4001  /* update minimum and maximum activities */
4002  if( SCIPconsIsTransformed(cons) )
4003  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4004 
4005  /* mark the constraint for propagation */
4006  if( SCIPconsIsTransformed(cons) )
4007  {
4008  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4009  }
4010 
4011  consdata->boundstightened = 0;
4012  consdata->presolved = FALSE;
4013  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4014  consdata->changed = TRUE;
4015  consdata->normalized = FALSE;
4016  consdata->upgradetried = FALSE;
4017  consdata->cliquesadded = FALSE;
4018  consdata->implsadded = FALSE;
4019  consdata->rangedrowpropagated = 0;
4020 
4021  return SCIP_OKAY;
4022 }
4023 
4024 /** scales a linear constraint with a constant scalar */
4025 static
4027  SCIP* scip, /**< SCIP data structure */
4028  SCIP_CONS* cons, /**< linear constraint to scale */
4029  SCIP_Real scalar /**< value to scale constraint with */
4030  )
4031 {
4032  SCIP_CONSDATA* consdata;
4033  SCIP_Real newval;
4034  SCIP_Real absscalar;
4035  int i;
4036 
4037  assert(scip != NULL);
4038  assert(cons != NULL);
4039 
4040  consdata = SCIPconsGetData(cons);
4041  assert(consdata != NULL);
4042  assert(consdata->row == NULL);
4043  assert(!SCIPisEQ(scip, scalar, 1.0));
4044 
4045  /* scale the coefficients */
4046  for( i = consdata->nvars - 1; i >= 0; --i )
4047  {
4048  newval = scalar * consdata->vals[i];
4049 
4050  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4051  * flooring down our new value
4052  */
4053  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4054  newval = SCIPfeasFloor(scip, newval + 0.5);
4055 
4056  if( SCIPisZero(scip, newval) )
4057  {
4058  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4059  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4060  SCIP_CALL( delCoefPos(scip, cons, i) );
4061  }
4062  else
4063  consdata->vals[i] = newval;
4064  }
4065 
4066  /* scale the sides */
4067  if( scalar < 0.0 )
4068  {
4069  SCIP_Real lhs;
4070 
4071  lhs = consdata->lhs;
4072  consdata->lhs = -consdata->rhs;
4073  consdata->rhs = -lhs;
4074  }
4075  absscalar = REALABS(scalar);
4076  if( !SCIPisInfinity(scip, -consdata->lhs) )
4077  {
4078  newval = absscalar * consdata->lhs;
4079 
4080  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4081  * flooring down our new value
4082  */
4083  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4084  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4085  else
4086  consdata->lhs = newval;
4087  }
4088  if( !SCIPisInfinity(scip, consdata->rhs) )
4089  {
4090  newval = absscalar * consdata->rhs;
4091 
4092  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4093  * our new value
4094  */
4095  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4096  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4097  else
4098  consdata->rhs = newval;
4099  }
4100 
4101  consdataInvalidateActivities(consdata);
4102  consdata->cliquesadded = FALSE;
4103  consdata->implsadded = FALSE;
4104 
4105  return SCIP_OKAY;
4106 }
4107 
4108 /* perform deletion of variables in all constraints of the constraint handler */
4109 static
4111  SCIP* scip, /**< SCIP data structure */
4112  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4113  SCIP_CONS** conss, /**< array of constraints */
4114  int nconss /**< number of constraints */
4115  )
4116 {
4117  SCIP_CONSDATA* consdata;
4118  int i;
4119  int v;
4120 
4121  assert(scip != NULL);
4122  assert(conshdlr != NULL);
4123  assert(conss != NULL);
4124  assert(nconss >= 0);
4125  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4126 
4127  /* iterate over all constraints */
4128  for( i = 0; i < nconss; i++ )
4129  {
4130  consdata = SCIPconsGetData(conss[i]);
4131 
4132  /* constraint is marked, that some of its variables were deleted */
4133  if( consdata->varsdeleted )
4134  {
4135  /* iterate over all variables of the constraint and delete them from the constraint */
4136  for( v = consdata->nvars - 1; v >= 0; --v )
4137  {
4138  if( SCIPvarIsDeleted(consdata->vars[v]) )
4139  {
4140  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4141  }
4142  }
4143  consdata->varsdeleted = FALSE;
4144  }
4145  }
4146 
4147  return SCIP_OKAY;
4148 }
4149 
4150 
4151 /** normalizes a linear constraint with the following rules:
4152  * - if all coefficients have them same absolute value, change them to (-)1.0
4153  * - multiplication with +1 or -1:
4154  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4155  * if the current rule doesn't determine the sign):
4156  * 1. the right hand side must not be negative
4157  * 2. the right hand side must not be infinite
4158  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4159  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4160  * 5. multiply with +1
4161  * - rationals to integrals
4162  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4163  * by the smallest common multiple of all denominators to get integral coefficients.
4164  * Forbid large denominators due to numerical stability.
4165  * - division by greatest common divisor
4166  * If all coefficients are integral, divide them by the greatest common divisor.
4167  */
4168 static
4170  SCIP* scip, /**< SCIP data structure */
4171  SCIP_CONS* cons, /**< linear constraint to normalize */
4172  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4173  )
4174 {
4175  SCIP_CONSDATA* consdata;
4176  SCIP_Real* vals;
4177  SCIP_Longint scm;
4178  SCIP_Longint nominator;
4179  SCIP_Longint denominator;
4180  SCIP_Longint gcd;
4181  SCIP_Longint maxmult;
4182  SCIP_Real epsilon;
4183  SCIP_Real feastol;
4184  SCIP_Real maxabsval;
4185  SCIP_Real minabsval;
4186  SCIP_Bool success;
4187  SCIP_Bool onlyintegral;
4188  int nvars;
4189  int mult;
4190  int nposcoeffs;
4191  int nnegcoeffs;
4192  int i;
4193  int v;
4194 
4195  assert(scip != NULL);
4196  assert(cons != NULL);
4197 
4198  *infeasible = FALSE;
4199 
4200  /* we must not change a modifiable constraint in any way */
4201  if( SCIPconsIsModifiable(cons) )
4202  return SCIP_OKAY;
4203 
4204  /* get constraint data */
4205  consdata = SCIPconsGetData(cons);
4206  assert(consdata != NULL);
4207 
4208  /* check, if the constraint is already normalized */
4209  if( consdata->normalized )
4210  return SCIP_OKAY;
4211 
4212  /* get coefficient arrays */
4213  vals = consdata->vals;
4214  nvars = consdata->nvars;
4215  assert(nvars == 0 || vals != NULL);
4216 
4217  if( nvars == 0 )
4218  {
4219  consdata->normalized = TRUE;
4220  return SCIP_OKAY;
4221  }
4222 
4223  assert(vals != NULL);
4224 
4225  /* get maximal and minimal absolute coefficient */
4226  maxabsval = consdataGetMaxAbsval(consdata);
4227  minabsval = consdataGetMinAbsval(consdata);
4228 
4229  /* return if scaling by maxval will eliminate coefficients */
4230  if( SCIPisZero(scip, minabsval/maxabsval) )
4231  return SCIP_OKAY;
4232 
4233  /* check if all coefficients are in absolute value equal, and not 1.0 */
4234  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4235  {
4236  SCIP_Bool abscoefsequ;
4237 
4238  abscoefsequ = TRUE;
4239 
4240  for( v = nvars - 1; v >= 0; --v )
4241  {
4242  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4243  {
4244  abscoefsequ = FALSE;
4245  break;
4246  }
4247  }
4248 
4249  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4250  if( abscoefsequ )
4251  {
4252  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4253  SCIPdebugPrintCons(scip, cons, NULL);
4254  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4255 
4256  if( consdata->validmaxabsval )
4257  {
4258  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4259  consdata->maxabsval = 1.0;
4260  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4261  consdata->minabsval = 1.0;
4262 
4263  maxabsval = 1.0;
4264  }
4265  else
4266  {
4267  /* get maximal absolute coefficient */
4268  maxabsval = consdataGetMaxAbsval(consdata);
4269  }
4270 
4271  /* get new consdata information, because scaleCons() might have deleted variables */
4272  vals = consdata->vals;
4273  nvars = consdata->nvars;
4274 
4275  assert(nvars == 0 || vals != NULL);
4276  }
4277  }
4278 
4279  /* nvars might have changed */
4280  if( nvars == 0 )
4281  {
4282  consdata->normalized = TRUE;
4283  return SCIP_OKAY;
4284  }
4285 
4286  assert(vals != NULL);
4287 
4288  /* calculate the maximal multiplier for common divisor calculation:
4289  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4290  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4291  * additionally, we don't want to scale the constraint if this would lead to too
4292  * large coefficients
4293  */
4294  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4295  feastol = SCIPfeastol(scip);
4296  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4297 
4298  if( !consdata->hasnonbinvalid )
4299  consdataCheckNonbinvar(consdata);
4300 
4301  /* if all variables are of integral type we will allow a greater multiplier */
4302  if( !consdata->hascontvar )
4303  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4304  else
4305  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4306 
4307  /*
4308  * multiplication with +1 or -1
4309  */
4310  mult = 0;
4311 
4312  /* 1. the right hand side must not be negative */
4313  if( SCIPisPositive(scip, consdata->lhs) )
4314  mult = +1;
4315  else if( SCIPisNegative(scip, consdata->rhs) )
4316  mult = -1;
4317 
4318  if( mult == 0 )
4319  {
4320  /* 2. the right hand side must not be infinite */
4321  if( SCIPisInfinity(scip, -consdata->lhs) )
4322  mult = +1;
4323  else if( SCIPisInfinity(scip, consdata->rhs) )
4324  mult = -1;
4325  }
4326 
4327  if( mult == 0 )
4328  {
4329  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4330  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4331  mult = +1;
4332  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4333  mult = -1;
4334  }
4335 
4336  if( mult == 0 )
4337  {
4338  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4339  nposcoeffs = 0;
4340  nnegcoeffs = 0;
4341  for( i = 0; i < nvars; ++i )
4342  {
4343  if( vals[i] > 0.0 )
4344  nposcoeffs++;
4345  else
4346  nnegcoeffs++;
4347  }
4348  if( nposcoeffs > nnegcoeffs )
4349  mult = +1;
4350  else if( nposcoeffs < nnegcoeffs )
4351  mult = -1;
4352  }
4353 
4354  if( mult == 0 )
4355  {
4356  /* 5. multiply with +1 */
4357  mult = +1;
4358  }
4359 
4360  assert(mult == +1 || mult == -1);
4361  if( mult == -1 )
4362  {
4363  /* scale the constraint with -1 */
4364  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4365  SCIPdebugPrintCons(scip, cons, NULL);
4366  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4367 
4368  /* scalecons() can delete variables, but scaling with -1 should not do that */
4369  assert(nvars == consdata->nvars);
4370  }
4371 
4372  /*
4373  * rationals to integrals
4374  *
4375  * @todo try scaling only on behalf of non-continuous variables
4376  */
4377  success = TRUE;
4378  scm = 1;
4379  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4380  {
4381  if( !SCIPisIntegral(scip, vals[i]) )
4382  {
4383  /* epsilon has been slightly decreased above - to be on the safe side */
4384  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4385  if( success )
4386  scm = SCIPcalcSmaComMul(scm, denominator);
4387  }
4388  }
4389  assert(scm >= 1);
4390 
4391  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4392  * their greatest common divisor
4393  */
4394  onlyintegral = TRUE;
4395  if( scm == 1 )
4396  {
4397  for( i = nvars - 1; i >= 0; --i )
4398  {
4399  if( !SCIPisIntegral(scip, vals[i]) )
4400  {
4401  onlyintegral = FALSE;
4402  break;
4403  }
4404  }
4405  }
4406 
4407  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4408  if( success && scm != 1 )
4409  {
4410  /* scale the constraint with the smallest common multiple of all denominators */
4411  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4412  SCIPdebugPrintCons(scip, cons, NULL);
4413  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4414 
4415  if( consdata->validmaxabsval )
4416  {
4417  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4418  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4419  {
4420  consdata->validmaxabsval = FALSE;
4421  consdata->maxabsval = SCIP_INVALID;
4422  consdataCalcMaxAbsval(consdata);
4423  }
4424  }
4425 
4426  if( consdata->validminabsval )
4427  {
4428  consdata->minabsval *= REALABS((SCIP_Real)scm);
4429  if( !SCIPisIntegral(scip, consdata->minabsval) )
4430  {
4431  consdata->validminabsval = FALSE;
4432  consdata->minabsval = SCIP_INVALID;
4433  consdataCalcMinAbsval(consdata);
4434  }
4435  }
4436 
4437  /* get new consdata information, because scalecons() might have deleted variables */
4438  vals = consdata->vals;
4439  nvars = consdata->nvars;
4440  assert(nvars == 0 || vals != NULL);
4441  }
4442 
4443  /*
4444  * division by greatest common divisor
4445  */
4446  if( success && nvars >= 1 )
4447  {
4448  /* all coefficients are integral: divide them by their greatest common divisor */
4449  assert(SCIPisIntegral(scip, vals[0]));
4450 
4451  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4452  for( i = 1; i < nvars && gcd > 1; ++i )
4453  {
4454  assert(SCIPisIntegral(scip, vals[i]));
4455  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4456  }
4457 
4458  if( gcd > 1 )
4459  {
4460  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4461  if( !consdata->hascontvar && onlyintegral )
4462  {
4463  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4464  {
4465  *infeasible = TRUE;
4466 
4467  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%g:\n", gcd);
4468  SCIPdebugPrintCons(scip, cons, NULL);
4469 
4470  return SCIP_OKAY;
4471  }
4472  }
4473 
4474  /* divide the constraint by the greatest common divisor of the coefficients */
4475  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4476  SCIPdebugPrintCons(scip, cons, NULL);
4477  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4478 
4479  if( consdata->validmaxabsval )
4480  {
4481  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4482  }
4483  if( consdata->validminabsval )
4484  {
4485  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4486  }
4487  }
4488  }
4489 
4490  /* mark constraint to be normalized */
4491  consdata->normalized = TRUE;
4492 
4493  SCIPdebugMsg(scip, "normalized constraint:\n");
4494  SCIPdebugPrintCons(scip, cons, NULL);
4495 
4496  return SCIP_OKAY;
4497 }
4498 
4499 /** replaces multiple occurrences of a variable by a single coefficient */
4500 static
4502  SCIP* scip, /**< SCIP data structure */
4503  SCIP_CONS* cons /**< linear constraint */
4504  )
4505 {
4506  SCIP_CONSDATA* consdata;
4507  SCIP_VAR* var;
4508  SCIP_Real valsum;
4509  int v;
4510 
4511  assert(scip != NULL);
4512  assert(cons != NULL);
4513 
4514  consdata = SCIPconsGetData(cons);
4515  assert(consdata != NULL);
4516 
4517  if( consdata->merged )
4518  return SCIP_OKAY;
4519 
4520  /* sort the constraint */
4521  SCIP_CALL( consdataSort(scip, consdata) );
4522 
4523  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4524  * backward direction is necessary, since delCoefPos() modifies the given position and
4525  * the subsequent ones
4526  */
4527  v = consdata->nvars-1;
4528  while( v >= 1 )
4529  {
4530  var = consdata->vars[v];
4531  if( consdata->vars[v-1] == var )
4532  {
4533  valsum = consdata->vals[v];
4534  do
4535  {
4536  SCIP_CALL( delCoefPos(scip, cons, v) );
4537  --v;
4538  valsum += consdata->vals[v];
4539  }
4540  while( v >= 1 && consdata->vars[v-1] == var );
4541 
4542  /* modify the last existing occurrence of the variable */
4543  assert(consdata->vars[v] == var);
4544  if( SCIPisZero(scip, valsum) )
4545  {
4546  SCIP_CALL( delCoefPos(scip, cons, v) );
4547 
4548  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4549  * delta needs to be recalculated on the next real propagation
4550  */
4551  if( consdata->maxactdeltavar == var )
4552  {
4553  consdata->maxactdelta = SCIP_INVALID;
4554  consdata->maxactdeltavar = NULL;
4555  }
4556  }
4557  else
4558  {
4559  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4560  }
4561  }
4562  --v;
4563  }
4564 
4565  consdata->merged = TRUE;
4566 
4567  return SCIP_OKAY;
4568 }
4569 
4570 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4571 static
4573  SCIP* scip, /**< SCIP data structure */
4574  SCIP_CONS* cons, /**< linear constraint */
4575  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4576  * information is not needed; in this case, we apply all fixings
4577  * instead of stopping after the first infeasible one */
4578  )
4579 {
4580  SCIP_CONSDATA* consdata;
4581  SCIP_VAR* var;
4582  SCIP_VAR** aggrvars;
4583  SCIP_Real val;
4584  SCIP_Real* aggrscalars;
4585  SCIP_Real fixedval;
4586  SCIP_Real aggrconst;
4587  int v;
4588  int naggrvars;
4589  int i;
4590 
4591  assert(scip != NULL);
4592  assert(cons != NULL);
4593 
4594  if( infeasible != NULL )
4595  *infeasible = FALSE;
4596 
4597  consdata = SCIPconsGetData(cons);
4598  assert(consdata != NULL);
4599 
4600  if( consdata->row != NULL && !SCIProwIsModifiable(consdata->row) )
4601  return SCIP_OKAY;
4602 
4603  if( !consdata->removedfixings )
4604  {
4605  SCIP_Real lhssubtrahend;
4606  SCIP_Real rhssubtrahend;
4607 
4608  lhssubtrahend = 0.0;
4609  rhssubtrahend = 0.0;
4610 
4611  SCIPdebugMsg(scip, "applying fixings:\n");
4612  SCIPdebugPrintCons(scip, cons, NULL);
4613 
4614  v = 0;
4615  while( v < consdata->nvars )
4616  {
4617  var = consdata->vars[v];
4618  val = consdata->vals[v];
4619  assert(SCIPvarIsTransformed(var));
4620 
4621  switch( SCIPvarGetStatus(var) )
4622  {
4624  SCIPerrorMessage("original variable in transformed linear constraint\n");
4625  return SCIP_INVALIDDATA;
4626 
4627  case SCIP_VARSTATUS_LOOSE:
4628  case SCIP_VARSTATUS_COLUMN:
4629  ++v;
4630  break;
4631 
4632  case SCIP_VARSTATUS_FIXED:
4633  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4634  fixedval = SCIPvarGetLbGlobal(var);
4635  if( !SCIPisInfinity(scip, -consdata->lhs) )
4636  {
4637  if( SCIPisInfinity(scip, ABS(fixedval)) )
4638  {
4639  if( val * fixedval > 0.0 )
4640  {
4641  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4642  }
4643  else
4644  {
4645  if( infeasible != NULL )
4646  {
4647  /* if lhs gets infinity it means that the problem is infeasible */
4648  *infeasible = TRUE;
4649  return SCIP_OKAY;
4650  }
4651  else
4652  {
4653  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4654  }
4655  }
4656  }
4657  else
4658  lhssubtrahend += val * fixedval;
4659  }
4660  if( !SCIPisInfinity(scip, consdata->rhs) )
4661  {
4662  if( SCIPisInfinity(scip, ABS(fixedval)) )
4663  {
4664  if( val * fixedval > 0.0 )
4665  {
4666  if( infeasible != NULL )
4667  {
4668  /* if rhs gets -infinity it means that the problem is infeasible */
4669  *infeasible = TRUE;
4670  return SCIP_OKAY;
4671  }
4672  else
4673  {
4674  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4675  }
4676  }
4677  else
4678  {
4679  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4680  }
4681  }
4682  else
4683  rhssubtrahend += val * fixedval;
4684  }
4685  SCIP_CALL( delCoefPos(scip, cons, v) );
4686  break;
4687 
4689  {
4690  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4691  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4692  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4693 
4694  assert(activevar != NULL);
4695  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4696  assert(activevar != NULL);
4697 
4698  if( !SCIPisZero(scip, activescalar) )
4699  {
4700  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4701  }
4702 
4703  if( !SCIPisZero(scip, activeconstant) )
4704  {
4705  if( !SCIPisInfinity(scip, -consdata->lhs) )
4706  lhssubtrahend += activeconstant;
4707  if( !SCIPisInfinity(scip, consdata->rhs) )
4708  rhssubtrahend += activeconstant;
4709  }
4710 
4711  SCIP_CALL( delCoefPos(scip, cons, v) );
4712  break;
4713  }
4716  naggrvars = SCIPvarGetMultaggrNVars(var);
4717  aggrvars = SCIPvarGetMultaggrVars(var);
4718  aggrscalars = SCIPvarGetMultaggrScalars(var);
4719  for( i = 0; i < naggrvars; ++i )
4720  {
4721  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4722  }
4723  aggrconst = SCIPvarGetMultaggrConstant(var);
4724 
4725  if( !SCIPisInfinity(scip, -consdata->lhs) )
4726  lhssubtrahend += val * aggrconst;
4727  if( !SCIPisInfinity(scip, consdata->rhs) )
4728  rhssubtrahend += val * aggrconst;
4729 
4730  SCIP_CALL( delCoefPos(scip, cons, v) );
4731  break;
4732 
4734  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4735  aggrconst = SCIPvarGetNegationConstant(var);
4736 
4737  if( !SCIPisInfinity(scip, -consdata->lhs) )
4738  lhssubtrahend += val * aggrconst;
4739  if( !SCIPisInfinity(scip, consdata->rhs) )
4740  rhssubtrahend += val * aggrconst;
4741 
4742  SCIP_CALL( delCoefPos(scip, cons, v) );
4743  break;
4744 
4745  default:
4746  SCIPerrorMessage("unknown variable status\n");
4747  SCIPABORT();
4748  return SCIP_INVALIDDATA; /*lint !e527*/
4749  }
4750  }
4751 
4752  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4753  {
4754  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4755  * causing wrong fixings of other variables --> better use a real zero here;
4756  * for small numbers, polishing the difference might lead to wrong results -->
4757  * better use the exact difference in this case
4758  */
4759  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4760  {
4761  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4762  }
4763  else
4764  {
4765  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4766  }
4767  }
4768  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4769  {
4770  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4771  * causing wrong fixings of other variables --> better use a real zero here;
4772  * for small numbers, polishing the difference might lead to wrong results -->
4773  * better use the exact difference in this case
4774  */
4775  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4776  {
4777  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4778  }
4779  else
4780  {
4781  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4782  }
4783  }
4784 
4785  consdata->removedfixings = TRUE;
4786 
4787  SCIPdebugMsg(scip, "after fixings:\n");
4788  SCIPdebugPrintCons(scip, cons, NULL);
4789 
4790  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4791  * to clean up the constraint
4792  */
4793  SCIP_CALL( mergeMultiples(scip, cons) );
4794 
4795  SCIPdebugMsg(scip, "after merging:\n");
4796  SCIPdebugPrintCons(scip, cons, NULL);
4797  }
4798  assert(consdata->removedfixings);
4799 
4800 #ifndef NDEBUG
4801  /* check, if all fixings are applied */
4802  for( v = 0; v < consdata->nvars; ++v )
4803  assert(SCIPvarIsActive(consdata->vars[v]));
4804 #endif
4805 
4806  return SCIP_OKAY;
4807 }
4808 
4809 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4810  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4811  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4812  * conflict detecting constraint by using NULL as inferred variable
4813  */
4814 static
4816  SCIP* scip, /**< SCIP data structure */
4817  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4818  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4819  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4820  int inferpos, /**< position of the inferred variable in the vars array */
4821  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4822  )
4823 {
4824  SCIP_CONSDATA* consdata;
4825  SCIP_VAR** vars;
4826  SCIP_Real* vals;
4827  int nvars;
4828  int i;
4829 
4830  assert(scip != NULL);
4831  assert(cons != NULL);
4833  consdata = SCIPconsGetData(cons);
4834 
4835  assert(consdata != NULL);
4836 
4837  vars = consdata->vars;
4838  vals = consdata->vals;
4839  nvars = consdata->nvars;
4840 
4841  assert(vars != NULL || nvars == 0);
4842  assert(vals != NULL || nvars == 0);
4843 
4844  assert(-1 <= inferpos && inferpos < nvars);
4845  assert((infervar == NULL) == (inferpos == -1));
4846  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4847 
4848  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4849  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4850  * - if the right hand side is the reason, the minimal residual activity is responsible
4851  * - if the left hand side is the reason, the maximal residual activity is responsible
4852  */
4853 
4854  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4855  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4856  {
4857  SCIP_Real minresactivity;
4858  SCIP_Real maxresactivity;
4859  SCIP_Bool minisrelax;
4860  SCIP_Bool maxisrelax;
4861  SCIP_Bool isminsettoinfinity;
4862  SCIP_Bool ismaxsettoinfinity;
4863 
4864  minresactivity = -SCIPinfinity(scip);
4865  maxresactivity = SCIPinfinity(scip);
4866 
4867  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4868  if( infervar != NULL )
4869  {
4870  assert(vals != NULL); /* for flexelint */
4871  if( reasonisrhs )
4872  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4873  &minisrelax, NULL, &isminsettoinfinity, NULL);
4874  else
4875  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4876  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4877  }
4878  else
4879  {
4880  if( reasonisrhs )
4881  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4882  &minisrelax, NULL, &isminsettoinfinity, NULL);
4883  else
4884  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4885  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4886  }
4887 
4888  /* we can only do something clever, if the residual activity is finite and not relaxed */
4889  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4890  {
4891  SCIP_Real rescap;
4892  SCIP_Bool resactisinf;
4893 
4894  resactisinf = FALSE;
4895 
4896  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4897  * than its inferred bound
4898  */
4899  if( infervar != NULL )
4900  {
4901  assert(vals != NULL); /* for flexelint */
4902 
4903  if( reasonisrhs )
4904  {
4905  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4906  {
4907  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4908  if( SCIPisInfinity(scip, -minresactivity) )
4909  resactisinf = TRUE;
4910  }
4911  rescap = consdata->rhs - minresactivity;
4912  }
4913  else
4914  {
4915  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4916  {
4917  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4918  if( SCIPisInfinity(scip, maxresactivity) )
4919  resactisinf = TRUE;
4920  }
4921  rescap = consdata->lhs - maxresactivity;
4922  }
4923 
4924  if( reasonisrhs == (vals[inferpos] > 0.0) )
4925  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4926  else
4927  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4928  }
4929  else
4930  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4931 
4932  if( !resactisinf )
4933  {
4934  /* now add bounds as reasons until the residual capacity is exceeded */
4935  for( i = 0; i < nvars; ++i )
4936  {
4937  assert( vars != NULL && vals != NULL ); /* for lint */
4938 
4939  /* zero coefficients and the infered variable can be ignored */
4940  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4941  continue;
4942 
4943  /* check if the residual capacity is exceeded */
4944  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4945  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4946  break;
4947 
4948  /* update the residual capacity due to the local bound of this variable */
4949  if( reasonisrhs == (vals[i] > 0.0) )
4950  {
4951  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4952  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4953  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4954  }
4955  else
4956  {
4957  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4958  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4959  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4960  }
4961  }
4962  return SCIP_OKAY;
4963  }
4964  }
4965  }
4966 
4967  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4968  for( i = 0; i < nvars; ++i )
4969  {
4970  assert(vars != NULL); /* for flexelint */
4971  assert(vals != NULL); /* for flexelint */
4972 
4973  /* zero coefficients and the infered variable can be ignored */
4974  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4975  continue;
4976 
4977  if( reasonisrhs == (vals[i] > 0.0) )
4978  {
4979  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4980  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4981  }
4982  else
4983  {
4984  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4985  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4986  }
4987  }
4988 
4989  return SCIP_OKAY;
4990 }
4991 
4992 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4993  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4994  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4995  */
4996 static
4998  SCIP* scip, /**< SCIP data structure */
4999  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5000  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5001  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5002  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5003  )
5004 {
5005  SCIP_CONSDATA* consdata;
5006  SCIP_VAR** vars;
5007  int nvars;
5008  int v;
5009 
5010  assert(scip != NULL);
5011  assert(cons != NULL);
5012 
5013  consdata = SCIPconsGetData(cons);
5014  assert(consdata != NULL);
5015  vars = consdata->vars;
5016  nvars = consdata->nvars;
5017  assert(vars != NULL || nvars == 0);
5018  assert(-1 <= inferpos && inferpos < nvars);
5019  assert((infervar == NULL) == (inferpos == -1));
5020  assert(inferpos == -1 || vars != NULL);
5021  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5022 
5023  /* collect all fixed variables */
5024  for( v = nvars - 1; v >= 0; --v )
5025  {
5026  assert(vars != NULL); /* for flexelint */
5027 
5028  /* need to add old bounds before propagation of inferrence variable */
5029  if( vars[v] == infervar )
5030  {
5031  assert(vars[v] != NULL);
5032 
5033  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5034  {
5035  /* @todo get boundchange index before this last boundchange and correct the index */
5036  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5037  }
5038 
5039  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5040  {
5041  /* @todo get boundchange index before this last boundchange and correct the index */
5042  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5043  }
5044 
5045  continue;
5046  }
5047 
5048  /* check for fixed variables */
5049  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5050  {
5051  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5052  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5053  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5054  }
5055  }
5056 
5057  return SCIP_OKAY;
5058 }
5059 
5060 /** add reasoning variables to conflict candidate queue which led to the conflict */
5061 static
5063  SCIP* scip, /**< SCIP data structure */
5064  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5065  int nvars, /**< number of variables reasoning the infeasibility */
5066  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5067  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5068  )
5069 {
5070  int v;
5071 
5072  assert(scip != NULL);
5073 
5074  /* collect all variables for which the local bounds differ from their global bounds */
5075  for( v = nvars - 1; v >= 0; --v )
5076  {
5077  assert(vars != NULL);
5078 
5079  /* check for local bound changes variables */
5080  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5081  {
5082  /* add conflict bound */
5083  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5084  }
5085 
5086  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5087  {
5088  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5089  }
5090  }
5091 
5092  if( var != NULL )
5093  {
5094  if( bound < SCIPvarGetLbLocal(var) )
5095  {
5096  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5097  }
5098 
5099  if( bound > SCIPvarGetUbLocal(var) )
5100  {
5101  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5102  }
5103  }
5104 
5105  return SCIP_OKAY;
5106 }
5107 
5108 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5109  * propagation rule (see propagateCons()):
5110  * (1) activity residuals of all other variables tighten bounds of single variable
5111  */
5112 static
5114  SCIP* scip, /**< SCIP data structure */
5115  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5116  SCIP_VAR* infervar, /**< variable that was deduced */
5117  INFERINFO inferinfo, /**< inference information */
5118  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5119  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5120  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5121  )
5122 {
5123  SCIP_CONSDATA* consdata;
5124  SCIP_VAR** vars;
5125 #ifndef NDEBUG
5126  SCIP_Real* vals;
5127 #endif
5128  int nvars;
5129  int inferpos;
5131  assert(scip != NULL);
5132  assert(cons != NULL);
5133  assert(result != NULL);
5134 
5135  consdata = SCIPconsGetData(cons);
5136  assert(consdata != NULL);
5137  vars = consdata->vars;
5138  nvars = consdata->nvars;
5139 #ifndef NDEBUG
5140  vals = consdata->vals;
5141  assert(vars != NULL);
5142  assert(vals != NULL);
5143 #endif
5144 
5145  /* get the position of the inferred variable in the vars array */
5146  inferpos = inferInfoGetPos(inferinfo);
5147  if( inferpos >= nvars || vars[inferpos] != infervar )
5148  {
5149  /* find inference variable in constraint */
5150  /**@todo use a binary search here; the variables can be sorted by variable index */
5151  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5152  {}
5153  }
5154  assert(inferpos < nvars);
5155  assert(vars[inferpos] == infervar);
5156  assert(!SCIPisZero(scip, vals[inferpos]));
5157 
5158  switch( inferInfoGetProprule(inferinfo) )
5159  {
5160  case PROPRULE_1_RHS:
5161  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5162  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5163  * domain in order to not exceed the right hand side of the inequality
5164  */
5165  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5166  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5167  *result = SCIP_SUCCESS;
5168  break;
5169 
5170  case PROPRULE_1_LHS:
5171  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5172  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5173  * domain in order to not fall below the left hand side of the inequality
5174  */
5175  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5176  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5177  *result = SCIP_SUCCESS;
5178  break;
5179 
5180  case PROPRULE_1_RANGEDROW:
5181  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5182  * the given inference variable to their bounds in this given ranged row
5183  */
5184 
5185  /* check that we really have a ranged row here */
5186  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5187  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5188  *result = SCIP_SUCCESS;
5189  break;
5190 
5191  case PROPRULE_INVALID:
5192  default:
5193  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5194  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5195  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5196  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5197  SCIPinfoMessage(scip, NULL, ";\n");
5198  return SCIP_INVALIDDATA;
5199  }
5200 
5201  return SCIP_OKAY;
5202 }
5203 
5204 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5205 static
5207  SCIP* scip, /**< SCIP data structure */
5208  SCIP_CONS* cons, /**< conflict detecting constraint */
5209  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5210  )
5211 {
5212  /* conflict analysis can only be applied in solving stage and if it is turned on */
5214  return SCIP_OKAY;
5215 
5216  /* initialize conflict analysis */
5218 
5219  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5220  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5221 
5222  /* analyze the conflict */
5224 
5225  return SCIP_OKAY;
5226 }
5227 
5228 /** check if there is any hope of tightening some bounds */
5229 static
5231  SCIP* scip, /**< SCIP data structure */
5232  SCIP_CONS* cons /**< linear constraint */
5233  )
5234 {
5235  SCIP_CONSDATA* consdata;
5236  int infcountmin;
5237  int infcountmax;
5238 
5239  consdata = SCIPconsGetData(cons);
5240  assert(consdata != NULL);
5241 
5242  infcountmin = consdata->minactivityneginf
5243  + consdata->minactivityposinf
5244  + consdata->minactivityneghuge
5245  + consdata->minactivityposhuge;
5246  infcountmax = consdata->maxactivityneginf
5247  + consdata->maxactivityposinf
5248  + consdata->maxactivityneghuge
5249  + consdata->maxactivityposhuge;
5250 
5251  if( infcountmin > 1 && infcountmax > 1 )
5252  return FALSE;
5253 
5254  return TRUE;
5255 }
5256 
5257 /** tighten upper bound */
5258 static
5260  SCIP* scip, /**< SCIP data structure */
5261  SCIP_CONS* cons, /**< linear constraint */
5262  int pos, /**< variable position */
5263  PROPRULE proprule, /**< propagation rule that deduced the value */
5264  SCIP_Real newub, /**< new upper bound */
5265  SCIP_Real oldub, /**< old upper bound */
5266  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5267  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5268  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5269  )
5270 {
5271  SCIP_CONSDATA* consdata;
5272  SCIP_VAR* var;
5273  SCIP_Real lb;
5274  SCIP_Bool infeasible;
5275  SCIP_Bool tightened;
5277  assert(cons != NULL);
5278  assert(!SCIPisInfinity(scip, newub));
5279 
5280  consdata = SCIPconsGetData(cons);
5281  assert(consdata != NULL);
5282  var = consdata->vars[pos];
5283  assert(var != NULL);
5284 
5285  lb = SCIPvarGetLbLocal(var);
5286  newub = SCIPadjustedVarUb(scip, var, newub);
5287 
5288  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5289  {
5290  SCIP_VARTYPE vartype;
5291 
5292  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5293  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5294 
5295  vartype = SCIPvarGetType(var);
5296 
5297  /* tighten upper bound */
5298  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5299 
5300  if( infeasible )
5301  {
5302  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5303  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5304 
5305  /* analyze conflict */
5306  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5307 
5308  *cutoff = TRUE;
5309  }
5310  else if( tightened )
5311  {
5312  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5313  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5314  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5315 
5316  (*nchgbds)++;
5317 
5318  /* if variable type was changed we might be able to upgrade the constraint */
5319  if( vartype != SCIPvarGetType(var) )
5320  consdata->upgradetried = FALSE;
5321  }
5322  }
5323  return SCIP_OKAY;
5324 }
5325 
5326 /** tighten lower bound */
5327 static
5329  SCIP* scip, /**< SCIP data structure */
5330  SCIP_CONS* cons, /**< linear constraint */
5331  int pos, /**< variable position */
5332  PROPRULE proprule, /**< propagation rule that deduced the value */
5333  SCIP_Real newlb, /**< new lower bound */
5334  SCIP_Real oldlb, /**< old lower bound */
5335  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5336  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5337  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5338  )
5339 {
5340  SCIP_CONSDATA* consdata;
5341  SCIP_VAR* var;
5342  SCIP_Real ub;
5343  SCIP_Bool infeasible;
5344  SCIP_Bool tightened;
5346  assert(cons != NULL);
5347  assert(!SCIPisInfinity(scip, newlb));
5348 
5349  consdata = SCIPconsGetData(cons);
5350  assert(consdata != NULL);
5351  var = consdata->vars[pos];
5352  assert(var != NULL);
5353 
5354  ub = SCIPvarGetUbLocal(var);
5355  newlb = SCIPadjustedVarLb(scip, var, newlb);
5356 
5357  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5358  {
5359  SCIP_VARTYPE vartype;
5360 
5361  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5362  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5363 
5364  vartype = SCIPvarGetType(var);
5365 
5366  /* tighten lower bound */
5367  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5368 
5369  if( infeasible )
5370  {
5371  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5372  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5373 
5374  /* analyze conflict */
5375  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5376 
5377  *cutoff = TRUE;
5378  }
5379  else if( tightened )
5380  {
5381  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5382  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5383  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5384 
5385  (*nchgbds)++;
5386 
5387  /* if variable type was changed we might be able to upgrade the constraint */
5388  if( vartype != SCIPvarGetType(var) )
5389  consdata->upgradetried = FALSE;
5390  }
5391  }
5392  return SCIP_OKAY;
5393 }
5394 
5395 /** tightens bounds of a single variable due to activity bounds (easy case) */
5396 static
5398  SCIP* scip, /**< SCIP data structure */
5399  SCIP_CONS* cons, /**< linear constraint */
5400  int pos, /**< position of the variable in the vars array */
5401  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5402  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5403  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5404  )
5405 {
5406  SCIP_CONSDATA* consdata;
5407  SCIP_VAR* var;
5408  SCIP_Real val;
5409  SCIP_Real lb;
5410  SCIP_Real ub;
5411  SCIP_Real lhs;
5412  SCIP_Real rhs;
5413 
5414  assert(scip != NULL);
5415  assert(cons != NULL);
5416  assert(cutoff != NULL);
5417  assert(nchgbds != NULL);
5418 
5419  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5420  if( SCIPconsIsModifiable(cons) )
5421  return SCIP_OKAY;
5422 
5423  consdata = SCIPconsGetData(cons);
5424  assert(consdata != NULL);
5425  assert(0 <= pos && pos < consdata->nvars);
5426 
5427  *cutoff = FALSE;
5428 
5429  var = consdata->vars[pos];
5430  assert(var != NULL);
5431 
5432  /* we cannot tighten bounds of multi-aggregated variables */
5434  return SCIP_OKAY;
5435 
5436  val = consdata->vals[pos];
5437  lhs = consdata->lhs;
5438  rhs = consdata->rhs;
5439  assert(!SCIPisZero(scip, val));
5440  assert(!SCIPisInfinity(scip, lhs));
5441  assert(!SCIPisInfinity(scip, -rhs));
5442 
5443  lb = SCIPvarGetLbLocal(var);
5444  ub = SCIPvarGetUbLocal(var);
5445  assert(SCIPisLE(scip, lb, ub));
5446 
5447  /* recompute activities if needed */
5448  if( !consdata->validactivities )
5449  consdataCalcActivities(scip, consdata);
5450  assert(consdata->validactivities);
5451  if( !consdata->validminact )
5452  consdataRecomputeMinactivity(scip, consdata);
5453  assert(consdata->validminact);
5454  if( !consdata->validmaxact )
5455  consdataRecomputeMaxactivity(scip, consdata);
5456  assert(consdata->validmaxact);
5457 
5458  if( val > 0.0 )
5459  {
5460  /* check, if we can tighten the variable's upper bound */
5461  if( !SCIPisInfinity(scip, rhs) )
5462  {
5463  SCIP_Real slack;
5464  SCIP_Real alpha;
5465 
5466  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5467  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5468  {
5469  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5470  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5471 
5472  *cutoff = TRUE;
5473  return SCIP_OKAY;
5474  }
5475 
5476  slack = rhs - consdata->minactivity;
5477 
5478  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5479  * it to zero
5480  */
5481  if( !SCIPisPositive(scip, slack) )
5482  slack = 0.0;
5483 
5484  alpha = val * (ub - lb);
5485  assert(!SCIPisNegative(scip, alpha));
5486 
5487  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5488  {
5489  SCIP_Real newub;
5490 
5491  /* compute new upper bound */
5492  newub = lb + (slack / val);
5493 
5494  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5495 
5496  if( *cutoff )
5497  {
5498  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5499  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5500 
5501  return SCIP_OKAY;
5502  }
5503 
5504  /* collect the new upper bound which is needed for the lower bound computation */
5505  ub = SCIPvarGetUbLocal(var);
5506  }
5507  }
5508 
5509  /* check, if we can tighten the variable's lower bound */
5510  if( !SCIPisInfinity(scip, -lhs) )
5511  {
5512  SCIP_Real slack;
5513  SCIP_Real alpha;
5514 
5515  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5516  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5517  {
5518  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5519  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5520 
5521  *cutoff = TRUE;
5522  return SCIP_OKAY;
5523  }
5524 
5525  slack = consdata->maxactivity - lhs;
5526 
5527  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5528  * it to zero
5529  */
5530  if( !SCIPisPositive(scip, slack) )
5531  slack = 0.0;
5532 
5533  alpha = val * (ub - lb);
5534  assert(!SCIPisNegative(scip, alpha));
5535 
5536  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5537  {
5538  SCIP_Real newlb;
5539 
5540  /* compute new lower bound */
5541  newlb = ub - (slack / val);
5542 
5543  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5544 
5545  if( *cutoff )
5546  {
5547  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5548  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5549 
5550  return SCIP_OKAY;
5551  }
5552  }
5553  }
5554  }
5555  else
5556  {
5557  /* check, if we can tighten the variable's lower bound */
5558  if( !SCIPisInfinity(scip, rhs) )
5559  {
5560  SCIP_Real slack;
5561  SCIP_Real alpha;
5562 
5563  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5564  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5565  {
5566  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5567  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5568 
5569  *cutoff = TRUE;
5570  return SCIP_OKAY;
5571  }
5572 
5573  slack = rhs - consdata->minactivity;
5574 
5575  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5576  * it to zero
5577  */
5578  if( !SCIPisPositive(scip, slack) )
5579  slack = 0.0;
5580 
5581  alpha = val * (lb - ub);
5582  assert(!SCIPisNegative(scip, alpha));
5583 
5584  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5585  {
5586  SCIP_Real newlb;
5587 
5588  /* compute new lower bound */
5589  newlb = ub + slack / val;
5590 
5591  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5592 
5593  if( *cutoff )
5594  {
5595  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5596  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5597 
5598  return SCIP_OKAY;
5599  }
5600  /* collect the new lower bound which is needed for the upper bound computation */
5601  lb = SCIPvarGetLbLocal(var);
5602  }
5603  }
5604 
5605  /* check, if we can tighten the variable's upper bound */
5606  if( !SCIPisInfinity(scip, -lhs) )
5607  {
5608  SCIP_Real slack;
5609  SCIP_Real alpha;
5610 
5611  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5612  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5613  {
5614  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5615  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5616 
5617  *cutoff = TRUE;
5618  return SCIP_OKAY;
5619  }
5620 
5621  slack = consdata->maxactivity - lhs;
5622 
5623  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5624  * it to zero
5625  */
5626  if( !SCIPisPositive(scip, slack) )
5627  slack = 0.0;
5628 
5629  alpha = val * (lb - ub);
5630  assert(!SCIPisNegative(scip, alpha));
5631 
5632  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5633  {
5634  SCIP_Real newub;
5635 
5636  /* compute new upper bound */
5637  newub = lb - (slack / val);
5638 
5639  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5640 
5641  if( *cutoff )
5642  {
5643  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5644  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5645 
5646  return SCIP_OKAY;
5647  }
5648  }
5649  }
5650  }
5651 
5652  return SCIP_OKAY;
5653 }
5654 
5655 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5656 static
5658  SCIP* scip, /**< SCIP data structure */
5659  SCIP_CONS* cons, /**< conflict detecting constraint */
5660  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5661  int nvars, /**< number of variables reasoning the infeasibility */
5662  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5663  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5664  )
5665 {
5666 #ifndef NDEBUG
5667  SCIP_CONSDATA* consdata;
5668 
5669  assert(scip != NULL);
5670  assert(cons != NULL);
5671 
5672  consdata = SCIPconsGetData(cons);
5673  assert(consdata != NULL);
5674  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5675 #endif
5676 
5677  /* conflict analysis can only be applied in solving stage and if it is turned on */
5679  return SCIP_OKAY;
5680 
5681  /* initialize conflict analysis */
5683 
5684  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5685  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5686 
5687  /* add reasoning variables to conflict candidate queue which led to the conflict */
5688  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5689 
5690  /* analyze the conflict */
5691  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5692 
5693  return SCIP_OKAY;
5694 }
5695 
5696 /** propagate ranged rows
5697  *
5698  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5699  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5700  * variables better.
5701  *
5702  * Example:
5703  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5704  *
5705  * x3 needs to be a multiple of 3, so the instance is infeasible.
5706  *
5707  * Example:
5708  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5709  *
5710  * The only possible value for x3 is 2, so the variable will be fixed.
5711  *
5712  * @todo add holes if possible
5713  */
5714 static
5716  SCIP* scip, /**< SCIP data structure */
5717  SCIP_CONS* cons, /**< linear constraint */
5718  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5719  int* nfixedvars, /**< pointer to count number of fixed variables */
5720  int* nchgbds, /**< pointer to count the number of bound changes */
5721  int* naddconss /**< pointer to count number of added constraints */
5722  )
5723 {
5724  SCIP_CONSHDLRDATA* conshdlrdata;
5725  SCIP_CONSHDLR* conshdlr;
5726  SCIP_CONSDATA* consdata;
5727  SCIP_VAR** infcheckvars;
5728  SCIP_Real* infcheckvals;
5729  SCIP_Real minactinfvars;
5730  SCIP_Real maxactinfvars;
5731  SCIP_Real lb;
5733  SCIP_Real feastol;
5734  SCIP_Real fixedact;
5735  SCIP_Real lhs;
5736  SCIP_Real rhs;
5737  SCIP_Real absminbincoef;
5738  SCIP_Longint gcd;
5739  SCIP_Longint gcdtmp;
5740  SCIP_Bool minactinfvarsinvalid;
5741  SCIP_Bool maxactinfvarsinvalid;
5742  SCIP_Bool possiblegcd;
5743  SCIP_Bool gcdisone;
5744  SCIP_Bool addartconss;
5745  int ninfcheckvars;
5746  int nunfixedvars;
5747  int nfixedconsvars;
5748  int ncontvars;
5749  int pos;
5750  int v;
5751 
5752  assert(scip != NULL);
5753  assert(cons != NULL);
5754  assert(cutoff != NULL);
5755  assert(nfixedvars != NULL);
5756  assert(nchgbds != NULL);
5757  assert(naddconss != NULL);
5758 
5759  /* modifiable constraint can be changed so we do not have all necessary information */
5760  if( SCIPconsIsModifiable(cons) )
5761  return SCIP_OKAY;
5762 
5763  consdata = SCIPconsGetData(cons);
5764  assert(consdata != NULL);
5765 
5766  /* we already did full ranged row propagation */
5767  if( consdata->rangedrowpropagated == 2 )
5768  return SCIP_OKAY;
5769 
5770  /* at least three variables are needed */
5771  if( consdata->nvars < 3 )
5772  return SCIP_OKAY;
5773 
5774  /* do nothing on normal inequalities */
5775  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5776  return SCIP_OKAY;
5777 
5778  /* get constraint handler data */
5779  conshdlr = SCIPconsGetHdlr(cons);
5780  assert(conshdlr != NULL);
5781  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5782  assert(conshdlrdata != NULL);
5783 
5784  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5785 
5786  /* we may add artificial constraints */
5787  if( addartconss )
5788  consdata->rangedrowpropagated = 2;
5789  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5790  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5791  * artificial constraints
5792  */
5793  else
5794  {
5795  if( consdata->rangedrowpropagated > 0 )
5796  return SCIP_OKAY;
5797 
5798  consdata->rangedrowpropagated = 1;
5799  }
5800  fixedact = 0;
5801  nfixedconsvars = 0;
5802  /* calculate fixed activity and number of fixed variables */
5803  for( v = consdata->nvars - 1; v >= 0; --v )
5804  {
5805  /* all zero coefficients should be eliminated */
5806  assert(!SCIPisZero(scip, consdata->vals[v]));
5807 
5808  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5809  {
5810  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5811  ++nfixedconsvars;
5812  }
5813  }
5814 
5815  /* do not work with huge fixed activities */
5816  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5817  return SCIP_OKAY;
5818 
5819  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5820  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5821  lhs = consdata->lhs - fixedact;
5822  rhs = consdata->rhs - fixedact;
5823  nunfixedvars = consdata->nvars - nfixedconsvars;
5824 
5825  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5826  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5827  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5828 
5829  absminbincoef = SCIP_REAL_MAX;
5830  ncontvars = 0;
5831  gcdisone = TRUE;
5832  possiblegcd = TRUE;
5833 
5834  /* we now partition all unfixed variables in two groups:
5835  *
5836  * the first one contains all integral variable with integral
5837  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5838  * given
5839  *
5840  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5841  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5842  */
5843 
5844  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5845  * variables
5846  */
5847  ninfcheckvars = 0;
5848  v = -1;
5849  pos = -1;
5850  do
5851  {
5852  ++v;
5853 
5854  /* partition the variables, do not change the order of collection, because it might be used later on */
5855  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5856  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5857  {
5858  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5859  {
5860  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5861  {
5862  ++ncontvars;
5863  }
5864  else if( SCIPvarIsBinary(consdata->vars[v]) )
5865  {
5866  SCIP_Real absval;
5867 
5868  absval = REALABS(consdata->vals[v]);
5869 
5870  if( absminbincoef > absval )
5871  absminbincoef = absval;
5872  }
5873 
5874  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5875  possiblegcd = FALSE;
5876  infcheckvars[ninfcheckvars] = consdata->vars[v];
5877  infcheckvals[ninfcheckvars] = consdata->vals[v];
5878  ++ninfcheckvars;
5879 
5880  if( pos == -1 )
5881  pos = v;
5882  }
5883  ++v;
5884  }
5885  }
5886  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5887 
5888  /* if the first group of variables is empty, we stop */
5889  /* @todo try to propagate/split up a constraint of the form:
5890  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5891  * with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1]
5892  */
5893  if( v == consdata->nvars )
5894  goto TERMINATE;
5895 
5896  /* we need at least two non-continuous variables */
5897  if( ncontvars + 2 > nunfixedvars )
5898  goto TERMINATE;
5899 
5900  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5901  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5902 
5903  feastol = SCIPfeastol(scip);
5904 
5905  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5906  assert(gcd >= 2);
5907 
5908  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5909  * calculate gcd over the first part of variables */
5910  for( ; v < consdata->nvars; ++v )
5911  {
5912  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5913  continue;
5914 
5915  if( SCIPvarIsBinary(consdata->vars[v]) )
5916  {
5917  SCIP_Real absval;
5918 
5919  absval = REALABS(consdata->vals[v]);
5920 
5921  if( absminbincoef > absval )
5922  absminbincoef = absval;
5923  }
5924 
5925  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5926  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5927  {
5928  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5929  ++ncontvars;
5930 
5931  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5932  possiblegcd = FALSE;
5933  infcheckvars[ninfcheckvars] = consdata->vars[v];
5934  infcheckvals[ninfcheckvars] = consdata->vals[v];
5935 
5936  ++ninfcheckvars;
5937 
5938  if( pos == -1 )
5939  pos = v;
5940  }
5941  else
5942  {
5943  assert(REALABS(consdata->vals[v]) > 1.5);
5944 
5945  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5946  assert(gcdtmp >= 1);
5947 
5948  if( gcdtmp == 1 )
5949  {
5950  infcheckvars[ninfcheckvars] = consdata->vars[v];
5951  infcheckvals[ninfcheckvars] = consdata->vals[v];
5952 
5953  ++ninfcheckvars;
5954 
5955  if( pos == -1 )
5956  pos = v;
5957  }
5958  else
5959  gcd = gcdtmp;
5960  }
5961  }
5962  assert(gcd >= 2);
5963 
5964  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5965  * normalizeCons() */
5966  if( ninfcheckvars == 0 )
5967  goto TERMINATE;
5968 
5969  assert(pos >= 0);
5970 
5971  minactinfvarsinvalid = FALSE;
5972  maxactinfvarsinvalid = FALSE;
5973  maxactinfvars = 0.0;
5974  minactinfvars = 0.0;
5975 
5976  /* calculate activities over all infcheckvars */
5977  for( v = ninfcheckvars - 1; v >= 0; --v )
5978  {
5979  lb = SCIPvarGetLbLocal(infcheckvars[v]);
5980  ub = SCIPvarGetUbLocal(infcheckvars[v]);
5981 
5982  if( SCIPisInfinity(scip, -lb) )
5983  {
5984  if( infcheckvals[v] < 0.0 )
5985  maxactinfvarsinvalid = TRUE;
5986  else
5987  minactinfvarsinvalid = TRUE;
5988  }
5989  else
5990  {
5991  if( infcheckvals[v] < 0.0 )
5992  maxactinfvars += infcheckvals[v] * lb;
5993  else
5994  minactinfvars += infcheckvals[v] * lb;
5995  }
5996 
5997  if( SCIPisInfinity(scip, ub) )
5998  {
5999  if( infcheckvals[v] > 0.0 )
6000  maxactinfvarsinvalid = TRUE;
6001  else
6002  minactinfvarsinvalid = TRUE;
6003  }
6004  else
6005  {
6006  if( infcheckvals[v] > 0.0 )
6007  maxactinfvars += infcheckvals[v] * ub;
6008  else
6009  minactinfvars += infcheckvals[v] * ub;
6010  }
6011 
6012  /* better abort on to big values */
6013  if( SCIPisHugeValue(scip, -minactinfvars) )
6014  minactinfvarsinvalid = TRUE;
6015  if( SCIPisHugeValue(scip, maxactinfvars) )
6016  maxactinfvarsinvalid = TRUE;
6017 
6018  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6019  goto TERMINATE;
6020  }
6021  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6022 
6023  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6024  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6025 
6026  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6027  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6028  * activities */
6029  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6030  * !!!note!!!
6031  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6032  * are not at their global bound
6033  */
6034 
6035  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6036  * infeasibility */
6037  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6038  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6039  {
6040  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6041  SCIPdebugPrintCons(scip, cons, NULL);
6042 
6043  /* start conflict analysis */
6044  /* @todo improve conflict analysis by adding relaxed bounds */
6045  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6046 
6047  *cutoff = TRUE;
6048  }
6049  else if( ncontvars == 0 )
6050  {
6051  SCIP_Longint gcdinfvars = -1;
6052 
6053  /* check for gcd over all infcheckvars */
6054  if( possiblegcd )
6055  {
6056  v = ninfcheckvars - 1;
6057  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6058  assert(gcdinfvars >= 2);
6059 
6060  for( ; v >= 0 && gcdinfvars >= 2; --v )
6061  {
6062  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6063  }
6064  }
6065  else if( gcdisone )
6066  gcdinfvars = 1;
6067 
6068  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6069 
6070  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6071  if( gcdinfvars >= 1 )
6072  {
6073  SCIP_Real value;
6074  SCIP_Real value2;
6075  SCIP_Real minvalue = SCIP_INVALID;
6076  SCIP_Real maxvalue = SCIP_INVALID;
6077  int nsols = 0;
6078 
6079  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6080 
6081  /* check how many possible solutions exist */
6082  while( SCIPisLE(scip, value, maxactinfvars) )
6083  {
6084  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6085 
6086  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6087  {
6088  ++nsols;
6089 
6090  /* early termination if we found more than two solutions */
6091  if( nsols == 3 )
6092  break;
6093 
6094  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6095  minvalue = value;
6096 
6097  maxvalue = value;
6098  }
6099  value += gcdinfvars;
6100  }
6101  assert(nsols < 2 || minvalue <= maxvalue);
6102 
6103  /* determine last possible solution for better bounding */
6104  if( nsols == 3 )
6105  {
6106 #ifndef NDEBUG
6107  SCIP_Real secondsolval = maxvalue;
6108 #endif
6109  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6110 
6111  /* check how many possible solutions exist */
6112  while( SCIPisGE(scip, value, minactinfvars) )
6113  {
6114  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6115 
6116  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6117  {
6118  maxvalue = value;
6119  assert(maxvalue > minvalue);
6120  break;
6121  }
6122  value -= gcdinfvars;
6123  }
6124  assert(maxvalue > secondsolval);
6125  }
6126 
6127  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6128  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6129 
6130  /* no possible solution found */
6131  if( nsols == 0 )
6132  {
6133  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6134  gcdinfvars, gcd, lhs, rhs);
6135  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6136  SCIPdebugPrintCons(scip, cons, NULL);
6137 
6138  /* start conflict analysis */
6139  /* @todo improve conflict analysis by adding relaxed bounds */
6140  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6141 
6142  *cutoff = TRUE;
6143  }
6144  /* if only one solution exist we can extract a new constraint or fix variables */
6145  else if( nsols == 1 )
6146  {
6147  assert(minvalue == maxvalue); /*lint !e777*/
6148 
6149  /* we can fix the only variable in our second set of variables */
6150  if( ninfcheckvars == 1 )
6151  {
6152  SCIP_Bool fixed;
6153 
6154  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6155 
6156  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6157  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6158  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6159 
6160  /* fix variable to only possible value */
6161  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6162  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6163 
6164  if( *cutoff )
6165  {
6166  /* start conflict analysis */
6167  /* @todo improve conflict analysis by adding relaxed bounds */
6168  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6169  }
6170 
6171  if( fixed )
6172  ++(*nfixedvars);
6173  }
6174  else
6175  {
6176  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6177  if( ninfcheckvars == nunfixedvars - 1 )
6178  {
6179  SCIP_Real bound;
6180  SCIP_Bool foundvar = FALSE;
6181  SCIP_Bool fixed;
6182  int w = 0;
6183 
6184  assert(ninfcheckvars > 0);
6185 
6186  /* find variable which is not an infcheckvar and fix it */
6187  for( v = 0; v < consdata->nvars - 1; ++v )
6188  {
6189  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6190  {
6191  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6192  {
6193 #ifndef NDEBUG
6194  int v2 = v + 1;
6195  int w2 = w;
6196 
6197  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6198 
6199  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6200  {
6201  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6202  continue;
6203 
6204  assert(consdata->vars[v2] == infcheckvars[w2]);
6205  ++w2;
6206  }
6207  assert(w2 == ninfcheckvars);
6208 #endif
6209  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6210 
6211  foundvar = TRUE;
6212 
6213  if( consdata->vals[v] < 0 )
6214  {
6215  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6216  }
6217  else
6218  {
6219  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6220  }
6221 
6222  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6223  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6224  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6225 
6226  /* fix variable to only possible value */
6227  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6228  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6229 
6230  if( *cutoff )
6231  {
6232  /* start conflict analysis */
6233  /* @todo improve conflict analysis by adding relaxed bounds */
6234  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6235  consdata->vars[v], bound) );
6236  }
6237 
6238  if( fixed )
6239  ++(*nfixedvars);
6240 
6241  break;
6242  }
6243 
6244  ++w;
6245  }
6246  }
6247 
6248  /* maybe last variable was the not infcheckvar */
6249  if( !foundvar )
6250  {
6251  assert(v == consdata->nvars - 1);
6252  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6253 
6254  if( consdata->vals[v] < 0 )
6255  {
6256  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6257  }
6258  else
6259  {
6260  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6261  }
6262 
6263  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6264  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6265  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6266 
6267  /* fix variable to only possible value */
6268  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6269  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6270 
6271  if( *cutoff )
6272  {
6273  /* start conflict analysis */
6274  /* @todo improve conflict analysis by adding relaxed bounds */
6275  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6276  consdata->vars[v], bound) );
6277  }
6278 
6279  if( fixed )
6280  ++(*nfixedvars);
6281  }
6282  }
6283  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6284  {
6285  /* aggregation possible if we have two variables, but this will be done later on */
6286  SCIP_CONS* newcons;
6287  char name[SCIP_MAXSTRLEN];
6288 
6289  /* create, add, and release new artificial constraint */
6290  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6291  ++conshdlrdata->naddconss;
6292 
6293  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6294 
6295  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6296  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6297  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6298 
6299  SCIPdebugPrintCons(scip, newcons, NULL);
6300 
6301  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6302 
6303  ++(*naddconss);
6304  }
6305  }
6306  }
6307  /* at least two solutions */
6308  else
6309  {
6310  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6311 
6312  /* only one variable in the second set, so we can bound this variables */
6313  if( ninfcheckvars == 1 )
6314  {
6315  SCIP_Bool tightened;
6316  SCIP_Real newlb;
6317  SCIP_Real newub;
6318 
6319  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6320 
6321  if( infcheckvals[0] < 0 )
6322  {
6323  newlb = maxvalue/infcheckvals[0];
6324  newub = minvalue/infcheckvals[0];
6325  }
6326  else
6327  {
6328  newlb = minvalue/infcheckvals[0];
6329  newub = maxvalue/infcheckvals[0];
6330  }
6331  assert(newlb < newub);
6332 
6333  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6334  {
6335  /* update lower bound of variable */
6336  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6337  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6338 
6339  /* tighten variable lower bound to minimal possible value */
6340  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6341  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6342 
6343  if( *cutoff )
6344  {
6345  /* start conflict analysis */
6346  /* @todo improve conflict analysis by adding relaxed bounds */
6347  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6348  }
6349 
6350  if( tightened )
6351  ++(*nchgbds);
6352  }
6353 
6354  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6355  {
6356  /* update upper bound of variable */
6357  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6358  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6359 
6360  /* tighten variable upper bound to maximal possible value */
6361  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6362  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6363 
6364  if( *cutoff )
6365  {
6366  /* start conflict analysis */
6367  /* @todo improve conflict analysis by adding relaxed bounds */
6368  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6369  }
6370 
6371  if( tightened )
6372  ++(*nchgbds);
6373  }
6374  }
6375  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6376  else if( ninfcheckvars == nunfixedvars - 1 )
6377  {
6378  SCIP_Bool foundvar = FALSE;
6379  SCIP_Bool tightened;
6380  SCIP_Real newlb;
6381  SCIP_Real newub;
6382  int w = 0;
6383 
6384  assert(ninfcheckvars > 0);
6385  assert(minvalue < maxvalue);
6386 
6387  /* find variable which is not an infcheckvar and fix it */
6388  for( v = 0; v < consdata->nvars - 1; ++v )
6389  {
6390  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6391  {
6392  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6393  {
6394 #ifndef NDEBUG
6395  int v2 = v + 1;
6396  int w2 = w;
6397 
6398  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6399 
6400  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6401  {
6402  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6403  continue;
6404 
6405  assert(consdata->vars[v2] == infcheckvars[w2]);
6406  ++w2;
6407  }
6408  assert(w2 == ninfcheckvars);
6409 #endif
6410 
6411  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6412  foundvar = TRUE;
6413 
6414  if( consdata->vals[v] < 0 )
6415  {
6416  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6417  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6418  }
6419  else
6420  {
6421  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6422  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6423  }
6424  assert(SCIPisLE(scip, newlb, newub));
6425 
6426  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6427  {
6428  /* update lower bound of variable */
6429  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6430  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6431 
6432  /* tighten variable lower bound to minimal possible value */
6433  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6434  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6435 
6436  if( *cutoff )
6437  {
6438  /* start conflict analysis */
6439  /* @todo improve conflict analysis by adding relaxed bounds */
6440  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6441  consdata->vars[v], newlb) );
6442  }
6443 
6444  if( tightened )
6445  ++(*nchgbds);
6446  }
6447 
6448  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6449  {
6450  /* update upper bound of variable */
6451  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6452  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6453 
6454  /* tighten variable upper bound to maximal possible value */
6455  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6456  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6457 
6458  if( *cutoff )
6459  {
6460  /* start conflict analysis */
6461  /* @todo improve conflict analysis by adding relaxed bounds */
6462  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6463  consdata->vars[v], newub) );
6464  }
6465 
6466  if( tightened )
6467  ++(*nchgbds);
6468  }
6469 
6470  break;
6471  }
6472 
6473  ++w;
6474  }
6475  }
6476 
6477  /* maybe last variable was the not infcheckvar */
6478  if( !foundvar )
6479  {
6480  assert(v == consdata->nvars - 1);
6481  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6482 
6483  if( consdata->vals[v] < 0 )
6484  {
6485  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6486  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6487  }
6488  else
6489  {
6490  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6491  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6492  }
6493  assert(SCIPisLE(scip, newlb, newub));
6494 
6495  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6496  {
6497  /* update lower bound of variable */
6498  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6499  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6500 
6501  /* tighten variable lower bound to minimal possible value */
6502  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6503  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6504 
6505  if( *cutoff )
6506  {
6507  /* start conflict analysis */
6508  /* @todo improve conflict analysis by adding relaxed bounds */
6509  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6510  }
6511 
6512  if( tightened )
6513  ++(*nchgbds);
6514  }
6515 
6516  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6517  {
6518  /* update upper bound of variable */
6519  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6520  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6521 
6522  /* tighten variable upper bound to maximal possible value */
6523  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6524  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6525 
6526  if( *cutoff )
6527  {
6528  /* start conflict analysis */
6529  /* @todo improve conflict analysis by adding relaxed bounds */
6530  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6531  }
6532 
6533  if( tightened )
6534  ++(*nchgbds);
6535  }
6536  }
6537  }
6538  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6539  * region for our infcheckvars, if possible
6540  */
6541  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6542  {
6543  SCIP_CONS* newcons;
6544  char name[SCIP_MAXSTRLEN];
6545  SCIP_Real newlhs;
6546  SCIP_Real newrhs;
6547 
6548  assert(maxvalue > minvalue);
6549 
6550  if( SCIPisGT(scip, minvalue, minactinfvars) )
6551  newlhs = minvalue;
6552  else
6553  newlhs = -SCIPinfinity(scip);
6554 
6555  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6556  newrhs = maxvalue;
6557  else
6558  newrhs = SCIPinfinity(scip);
6559 
6560  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6561  {
6562  /* create, add, and release new artificial constraint */
6563  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6564  ++conshdlrdata->naddconss;
6565 
6566  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6567 
6568  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6569  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6570  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6571 
6572  SCIPdebugPrintCons(scip, newcons, NULL);
6573  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6574 
6575  ++(*naddconss);
6576  }
6577  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6578  * should be maxvalue */
6579  }
6580  }
6581  }
6582  }
6583  else if( addartconss && ncontvars < ninfcheckvars )
6584  {
6585  SCIP_Real maxact = 0.0;
6586  SCIP_Real minact = 0.0;
6587  int w = 0;
6588 
6589  /* compute activities of non-infcheckvars */
6590  for( v = 0; v < consdata->nvars; ++v )
6591  {
6592  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6593  {
6594  ++w;
6595  continue;
6596  }
6597 
6598  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6599  {
6600  if( SCIPvarIsBinary(consdata->vars[v]) )
6601  {
6602  if( consdata->vals[v] > 0.0 )
6603  maxact += consdata->vals[v];
6604  else
6605  minact += consdata->vals[v];
6606  }
6607  else
6608  {
6609  SCIP_Real tmpval;
6610 
6611  assert(SCIPvarIsIntegral(consdata->vars[v]));
6612 
6613  if( consdata->vals[v] > 0.0 )
6614  {
6615  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6616 
6617  if( SCIPisHugeValue(scip, -tmpval) )
6618  break;
6619 
6620  minact += tmpval;
6621 
6622  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6623 
6624  if( SCIPisHugeValue(scip, tmpval) )
6625  break;
6626 
6627  maxact += tmpval;
6628  }
6629  else
6630  {
6631  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6632 
6633  if( SCIPisHugeValue(scip, -tmpval) )
6634  break;
6635 
6636  minact += tmpval;
6637 
6638  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6639 
6640  if( SCIPisHugeValue(scip, tmpval) )
6641  break;
6642 
6643  maxact += tmpval;
6644  }
6645  }
6646  }
6647  }
6648  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6649  {
6650  SCIP_CONS* newcons;
6651  char name[SCIP_MAXSTRLEN];
6652  SCIP_Real newlhs;
6653  SCIP_Real newrhs;
6654 
6655  assert(maxact > minact);
6656  assert(w == ninfcheckvars);
6657 
6658  newlhs = lhs - maxact;
6659  newrhs = rhs - minact;
6660  assert(newlhs < newrhs);
6661 
6662  /* create, add, and release new artificial constraint */
6663  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6664  ++conshdlrdata->naddconss;
6665 
6666  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6667 
6668  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6669  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6670  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6671 
6672  SCIPdebugPrintCons(scip, newcons, NULL);
6673  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6674 
6675  ++(*naddconss);
6676  }
6677  }
6678 
6679  TERMINATE:
6680  SCIPfreeBufferArray(scip, &infcheckvals);
6681  SCIPfreeBufferArray(scip, &infcheckvars);
6682 
6683  return SCIP_OKAY;
6684 }
6685 
6686 /** tightens bounds of a single variable due to activity bounds */
6687 static
6689  SCIP* scip, /**< SCIP data structure */
6690  SCIP_CONS* cons, /**< linear constraint */
6691  int pos, /**< position of the variable in the vars array */
6692  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6693  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6694  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6695  )
6696 {
6697  SCIP_CONSDATA* consdata;
6698  SCIP_VAR* var;
6699  SCIP_Real val;
6700  SCIP_Real lb;
6701  SCIP_Real ub;
6702  SCIP_Real minresactivity;
6703  SCIP_Real maxresactivity;
6704  SCIP_Real lhs;
6706  SCIP_Bool infeasible;
6707  SCIP_Bool tightened;
6708  SCIP_Bool minisrelax;
6709  SCIP_Bool maxisrelax;
6710  SCIP_Bool isminsettoinfinity;
6711  SCIP_Bool ismaxsettoinfinity;
6712 
6713  assert(scip != NULL);
6714  assert(cons != NULL);
6715  assert(cutoff != NULL);
6716  assert(nchgbds != NULL);
6717 
6718  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6719  if( SCIPconsIsModifiable(cons) )
6720  return SCIP_OKAY;
6721 
6722  consdata = SCIPconsGetData(cons);
6723  assert(consdata != NULL);
6724  assert(0 <= pos && pos < consdata->nvars);
6725 
6726  *cutoff = FALSE;
6727 
6728  var = consdata->vars[pos];
6729 
6730  /* we cannot tighten bounds of multi-aggregated variables */
6732  return SCIP_OKAY;
6733 
6734  val = consdata->vals[pos];
6735  lhs = consdata->lhs;
6736  rhs = consdata->rhs;
6737  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6738  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6739  assert(var != NULL);
6740  assert(!SCIPisZero(scip, val));
6741  assert(!SCIPisInfinity(scip, lhs));
6742  assert(!SCIPisInfinity(scip, -rhs));
6743 
6744  lb = SCIPvarGetLbLocal(var);
6745  ub = SCIPvarGetUbLocal(var);
6746  assert(SCIPisLE(scip, lb, ub));
6747 
6748  if( val > 0.0 )
6749  {
6750  /* check, if we can tighten the variable's bounds */
6751  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6752  {
6753  SCIP_Real newub;
6754 
6755  newub = (rhs - minresactivity)/val;
6756 
6757  if( !SCIPisInfinity(scip, newub) &&
6758  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6759  {
6760  SCIP_Bool activityunreliable;
6761  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6762 
6763  /* check minresactivities for reliability */
6764  if( activityunreliable )
6765  {
6766  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6767  newub = (rhs - minresactivity)/val;
6768  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6769  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6770  && (!force || !SCIPisLT(scip, newub, ub)));
6771  }
6772 
6773  if( !activityunreliable )
6774  {
6775  /* tighten upper bound */
6776  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6777  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6778  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6779  &infeasible, &tightened) );
6780  if( infeasible )
6781  {
6782  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6783  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6784 
6785  /* analyze conflict */
6786  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6787 
6788  *cutoff = TRUE;
6789  return SCIP_OKAY;
6790  }
6791  if( tightened )
6792  {
6793  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6794  assert(SCIPisFeasLE(scip, ub, newub));
6795  (*nchgbds)++;
6796 
6797  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6798  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6799  }
6800  }
6801  }
6802  }
6803 
6804  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6805  {
6806  SCIP_Real newlb;
6807 
6808  newlb = (lhs - maxresactivity)/val;
6809  if( !SCIPisInfinity(scip, -newlb) &&
6810  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6811  {
6812  /* check maxresactivities for reliability */
6813  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6814  {
6815  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6816  newlb = (lhs - maxresactivity)/val;
6817 
6818  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6819  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6820  && (!force || !SCIPisGT(scip, newlb, lb))) )
6821  return SCIP_OKAY;
6822  }
6823 
6824  /* tighten lower bound */
6825  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6826  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6827  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6828  &infeasible, &tightened) );
6829  if( infeasible )
6830  {
6831  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6832  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6833 
6834  /* analyze conflict */
6835  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6836 
6837  *cutoff = TRUE;
6838  return SCIP_OKAY;
6839  }
6840  if( tightened )
6841  {
6842  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6843  assert(SCIPisFeasGE(scip, lb, newlb));
6844  (*nchgbds)++;
6845  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6846  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6847  }
6848  }
6849  }
6850  }
6851  else
6852  {
6853  /* check, if we can tighten the variable's bounds */
6854  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6855  {
6856  SCIP_Real newlb;
6857 
6858  newlb = (rhs - minresactivity)/val;
6859  if( !SCIPisInfinity(scip, -newlb) &&
6860  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6861  {
6862  SCIP_Bool activityunreliable;
6863  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6864  /* check minresactivities for reliability */
6865  if( activityunreliable )
6866  {
6867  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6868  newlb = (rhs - minresactivity)/val;
6869 
6870  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6871  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6872  && (!force || !SCIPisGT(scip, newlb, lb)));
6873  }
6874 
6875  if( !activityunreliable )
6876  {
6877  /* tighten lower bound */
6878  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6879  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6880  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6881  &infeasible, &tightened) );
6882  if( infeasible )
6883  {
6884  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6885  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6886 
6887  /* analyze conflict */
6888  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6889 
6890  *cutoff = TRUE;
6891  return SCIP_OKAY;
6892  }
6893  if( tightened )
6894  {
6895  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6896  assert(SCIPisFeasGE(scip, lb, newlb));
6897  (*nchgbds)++;
6898  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6899  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6900  }
6901  }
6902  }
6903  }
6904 
6905  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6906  {
6907  SCIP_Real newub;
6908 
6909  newub = (lhs - maxresactivity)/val;
6910  if( !SCIPisInfinity(scip, newub) &&
6911  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6912  {
6913  /* check maxresactivities for reliability */
6914  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6915  {
6916  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6917  newub = (lhs - maxresactivity)/val;
6918 
6919  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6920  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6921  && (!force || !SCIPisLT(scip, newub, ub))) )
6922  return SCIP_OKAY;
6923  }
6924 
6925  /* tighten upper bound */
6926  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6927  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6928  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6929  &infeasible, &tightened) );
6930  if( infeasible )
6931  {
6932  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6933  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6934 
6935  /* analyze conflict */
6936  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6937 
6938  *cutoff = TRUE;
6939  return SCIP_OKAY;
6940  }
6941  if( tightened )
6942  {
6943  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6944  assert(SCIPisFeasLE(scip, ub, newub));
6945  (*nchgbds)++;
6946  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6947  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6948  }
6949  }
6950  }
6951  }
6952 
6953  return SCIP_OKAY;
6954 }
6955 
6956 #define MAXTIGHTENROUNDS 10
6957 
6958 /** tightens bounds of variables in constraint due to activity bounds */
6959 static
6961  SCIP* scip, /**< SCIP data structure */
6962  SCIP_CONS* cons, /**< linear constraint */
6963  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6964  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6965  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6966  int* nchgbds /**< pointer to count the total number of tightened bounds */
6967  )
6968 {
6969  SCIP_CONSDATA* consdata;
6970  unsigned int tightenmode;
6971  int nvars;
6972  int nrounds;
6973  int lastchange;
6974  int oldnchgbds;
6975 #ifndef SCIP_DEBUG
6976  int oldnchgbdstotal;
6977 #endif
6978  int v;
6979  SCIP_Bool force;
6980  SCIP_Bool easycase;
6981 
6982  assert(scip != NULL);
6983  assert(cons != NULL);
6984  assert(nchgbds != NULL);
6985  assert(cutoff != NULL);
6986 
6987  *cutoff = FALSE;
6988 
6989  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6990  if( SCIPconsIsModifiable(cons) )
6991  return SCIP_OKAY;
6992 
6993  /* if a constraint was created after presolve, then it may hold fixed variables
6994  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
6995  * thus, ensure here again that variable fixings have been applied
6996  */
6997  SCIP_CALL( applyFixings(scip, cons, cutoff) );
6998  if( *cutoff )
6999  return SCIP_OKAY;
7000 
7001  /* check if constraint has any chances of tightening bounds */
7002  if( !canTightenBounds(scip, cons) )
7003  return SCIP_OKAY;
7004 
7005  consdata = SCIPconsGetData(cons);
7006  assert(consdata != NULL);
7007 
7008  nvars = consdata->nvars;
7009  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7010 
7011  /* we are at the root node or during presolving */
7012  if( SCIPgetDepth(scip) < 1 )
7013  tightenmode = 2;
7014  else
7015  tightenmode = 1;
7016 
7017  /* stop if we already tightened the constraint and the tightening is not forced */
7018  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7019  return SCIP_OKAY;
7020 
7021  /* ensure that the variables are properly sorted */
7022  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
7023  {
7024  SCIP_CALL( consdataSort(scip, consdata) );
7025  assert(consdata->binvarssorted);
7026  }
7027 
7028  /* update maximal activity delta if necessary */
7029  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7030  consdataRecomputeMaxActivityDelta(scip, consdata);
7031 
7032  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7033  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7034  checkMaxActivityDelta(scip, consdata);
7035 
7036  /* this may happen if all variables are fixed */
7037  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7038  return SCIP_OKAY;
7039 
7040  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7041  {
7042  SCIP_Real slack;
7043  SCIP_Real surplus;
7044  SCIP_Real minactivity;
7045  SCIP_Real maxactivity;
7046  SCIP_Bool minisrelax;
7047  SCIP_Bool maxisrelax;
7048 
7049  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7050  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
7051  assert(!SCIPisInfinity(scip, minactivity));
7052  assert(!SCIPisInfinity(scip, -maxactivity));
7053 
7054  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7055  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7056 
7057  /* check if the constraint will propagate */
7058  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7059  return SCIP_OKAY;
7060  }
7061 
7062  /* check if we can use fast implementation for easy and numerically well behaved cases */
7063  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7064 
7065  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7066  lastchange = -1;
7067  oldnchgbds = 0;
7068 
7069 #ifndef SCIP_DEBUG
7070  oldnchgbdstotal = *nchgbds;
7071 #endif
7072 
7073  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7074  {
7075  /* mark the constraint to have the variables' bounds tightened */
7076  consdata->boundstightened = (unsigned int)tightenmode;
7077 
7078  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7079  * sorting enables skipping variables
7080  */
7081  v = 0;
7082  while( v < nvars && v != lastchange && !(*cutoff) )
7083  {
7084  oldnchgbds = *nchgbds;
7085 
7086  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
7087 
7088  if( easycase )
7089  {
7090  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7091  }
7092  else
7093  {
7094  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7095  }
7096 
7097  /* if there was no progress, skip the rest of the binary variables */
7098  if( *nchgbds > oldnchgbds )
7099  {
7100  lastchange = v;
7101  ++v;
7102  }
7103  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
7104  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7105  v = consdata->nbinvars;
7106  else
7107  ++v;
7108  }
7109 
7110 #ifndef SCIP_DEBUG
7111  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7112  *nchgbds - oldnchgbdstotal, nrounds);
7113  oldnchgbdstotal += oldnchgbds;
7114 #endif
7115  }
7116 
7117 #ifndef NDEBUG
7118  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7119  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7120 #endif
7121 
7122  return SCIP_OKAY;
7123 }
7124 
7125 /** checks linear constraint for feasibility of given solution or current solution */
7126 static
7128  SCIP* scip, /**< SCIP data structure */
7129  SCIP_CONS* cons, /**< linear constraint */
7130  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7131  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7132  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7133  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7134  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7135  )
7136 {
7137  SCIP_CONSDATA* consdata;
7138  SCIP_Real activity;
7139  SCIP_Real absviol;
7140  SCIP_Real relviol;
7141  SCIP_Real lhsviol;
7142  SCIP_Real rhsviol;
7143 
7144  assert(scip != NULL);
7145  assert(cons != NULL);
7146  assert(violated != NULL);
7147 
7148  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7149  SCIPdebugPrintCons(scip, cons, NULL);
7150 
7151  consdata = SCIPconsGetData(cons);
7152  assert(consdata != NULL);
7153 
7154  *violated = FALSE;
7155 
7156  if( consdata->row != NULL )
7157  {
7158  if( !checklprows && SCIProwIsInLP(consdata->row) )
7159  return SCIP_OKAY;
7160  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7161  activity = consdataComputePseudoActivity(scip, consdata);
7162  else
7163  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7164  }
7165  else
7166  activity = consdataGetActivity(scip, consdata, sol);
7167 
7168  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7169  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7170  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7171  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7172 
7173  /* calculate absolute and relative bound violations */
7174  lhsviol = consdata->lhs - activity;
7175  rhsviol = activity - consdata->rhs;
7176 
7177  absviol = 0.0;
7178  relviol = 0.0;
7179  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7180  {
7181  absviol = lhsviol;
7182  relviol = SCIPrelDiff(consdata->lhs, activity);
7183  }
7184  else if( rhsviol > 0 )
7185  {
7186  absviol = rhsviol;
7187  relviol = SCIPrelDiff(activity, consdata->rhs);
7188  }
7189 
7190  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7191  * return infeasible for safety
7192  */
7193  if( activity == SCIP_INVALID ) /*lint !e777*/
7194  {
7195  assert(sol == NULL);
7196  *violated = TRUE;
7197 
7198  /* set violation of invalid pseudo solutions */
7199  absviol = SCIP_INVALID;
7200  relviol = SCIP_INVALID;
7201 
7202  /* reset constraint age since we are in enforcement */
7203  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7204  }
7205  /* check with relative tolerances (the default) */
7206  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7207  {
7208  /* the "normal" check: one of the two sides is violated */
7209  if( !checkrelmaxabs )
7210  {
7211  *violated = TRUE;
7212 
7213  /* only reset constraint age if we are in enforcement */
7214  if( sol == NULL )
7215  {
7216  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7217  }
7218  }
7219  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7220  * small compared to the absolute values occurring in the activity
7221  */
7222  else
7223  {
7224  SCIP_Real maxabs;
7225  SCIP_Real coef;
7226  SCIP_Real absval;
7227  SCIP_Real solval;
7228  int v;
7229 
7230  maxabs = 1.0;
7231 
7232  /* compute maximum absolute value */
7233  for( v = 0; v < consdata->nvars; ++v )
7234  {
7235  if( consdata->vals != NULL )
7236  {
7237  coef = consdata->vals[v];
7238  }
7239  else
7240  coef = 1.0;
7241 
7242  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7243  absval = REALABS( coef * solval );
7244  maxabs = MAX( maxabs, absval );
7245  }
7246 
7247  /* regard left hand side, first */
7248  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7249  {
7250  /* check whether violation is random noise */
7251  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7252  {
7253  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7254  consdata->lhs - activity, maxabs);
7255  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7256 
7257  /* only increase constraint age if we are in enforcement */
7258  if( sol == NULL )
7259  {
7260  SCIP_CALL( SCIPincConsAge(scip, cons) );
7261  }
7262  }
7263  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7264  else if( SCIPisZero(scip, consdata->lhs) )
7265  {
7266  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7267  {
7268  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7269  consdata->lhs - activity, maxabs);
7270  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7271 
7272  /* only increase constraint age if we are in enforcement */
7273  if( sol == NULL )
7274  {
7275  SCIP_CALL( SCIPincConsAge(scip, cons) );
7276  }
7277  }
7278  else
7279  {
7280  *violated = TRUE;
7281 
7282  /* only reset constraint age if we are in enforcement */
7283  if( sol == NULL )
7284  {
7285  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7286  }
7287  }
7288  }
7289  else
7290  {
7291  *violated = TRUE;
7292 
7293  /* only reset constraint age if we are in enforcement */
7294  if( sol == NULL )
7295  {
7296  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7297  }
7298  }
7299  }
7300 
7301  /* now regard right hand side */
7302  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7303  {
7304  /* check whether violation is random noise */
7305  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7306  {
7307  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7308  activity - consdata->rhs, maxabs);
7309  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7310 
7311  /* only increase constraint age if we are in enforcement */
7312  if( sol == NULL )
7313  {
7314  SCIP_CALL( SCIPincConsAge(scip, cons) );
7315  }
7316  }
7317  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7318  else if( SCIPisZero(scip, consdata->rhs) )
7319  {
7320  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7321  {
7322  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7323  activity - consdata->rhs, maxabs);
7324  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7325 
7326  /* only increase constraint age if we are in enforcement */
7327  if( sol == NULL )
7328  {
7329  SCIP_CALL( SCIPincConsAge(scip, cons) );
7330  }
7331  }
7332  else
7333  {
7334  *violated = TRUE;
7335 
7336  /* only reset constraint age if we are in enforcement */
7337  if( sol == NULL )
7338  {
7339  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7340  }
7341  }
7342  }
7343  else
7344  {
7345  *violated = TRUE;
7346 
7347  /* only reset constraint age if we are in enforcement */
7348  if( sol == NULL )
7349  {
7350  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7351  }
7352  }
7353  }
7354  }
7355  }
7356  /* check with absolute tolerances */
7357  else if( consdata->checkabsolute &&
7358  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7359  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7360  {
7361  *violated = TRUE;
7362 
7363  /* only reset constraint age if we are in enforcement */
7364  if( sol == NULL )
7365  {
7366  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7367  }
7368  }
7369  else
7370  {
7371  /* only increase constraint age if we are in enforcement */
7372  if( sol == NULL )
7373  {
7374  SCIP_CALL( SCIPincConsAge(scip, cons) );
7375  }
7376  }
7377 
7378  /* update absolute and relative violation of the solution */
7379  if( sol != NULL )
7380  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7381 
7382  return SCIP_OKAY;
7383 }
7384 
7385 /** creates an LP row in a linear constraint data */
7386 static
7388  SCIP* scip, /**< SCIP data structure */
7389  SCIP_CONS* cons /**< linear constraint */
7390  )
7391 {
7392  SCIP_CONSDATA* consdata;
7393 
7394  assert(scip != NULL);
7395  assert(cons != NULL);
7396 
7397  consdata = SCIPconsGetData(cons);
7398  assert(consdata != NULL);
7399  assert(consdata->row == NULL);
7400 
7401  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7403 
7404  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7405 
7406  return SCIP_OKAY;
7407 }
7408 
7409 /** adds linear constraint as cut to the LP */
7410 static
7412  SCIP* scip, /**< SCIP data structure */
7413  SCIP_CONS* cons, /**< linear constraint */
7414  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7415  )
7416 {
7417  SCIP_CONSDATA* consdata;
7418 
7419  assert(scip != NULL);
7420  assert(cons != NULL);
7421 
7422  consdata = SCIPconsGetData(cons);
7423  assert(consdata != NULL);
7424 
7425  if( consdata->row == NULL )
7426  {
7427  /* convert consdata object into LP row */
7428  SCIP_CALL( createRow(scip, cons) );
7429  }
7430  assert(consdata->row != NULL);
7431 
7432  if( consdata->nvars == 0 )
7433  {
7434  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7435  }
7436 
7437  /* insert LP row as cut */
7438  if( !SCIProwIsInLP(consdata->row) )
7439  {
7440  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7441  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7442  /* if presolving is turned off, the row might be trivial */
7443  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7444  {
7445  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7446  }
7447 #ifndef NDEBUG
7448  else
7449  {
7450  int pr;
7451  int cr;
7452  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7453  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7454  assert( pr == 0 || cr == 0 );
7455  }
7456 #endif
7457  }
7458 
7459  return SCIP_OKAY;
7460 }
7461 
7462 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7463 static
7465  SCIP* scip, /**< SCIP data structure */
7466  SCIP_CONS* cons, /**< linear constraint */
7467  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7468  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7469  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7470  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7471  * the ones with non-zero dual value? */
7472  int* ncuts, /**< pointer to add up the number of found cuts */
7473  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7474  )
7475 {
7476  SCIP_CONSDATA* consdata;
7477  SCIP_Bool violated;
7478  int oldncuts;
7479 
7480  assert(scip != NULL);
7481  assert(conshdlrdata != NULL);
7482  assert(cons != NULL);
7483  assert(cutoff != NULL);
7484 
7485  consdata = SCIPconsGetData(cons);
7486  assert(ncuts != NULL);
7487  assert(consdata != NULL);
7488 
7489  oldncuts = *ncuts;
7490  *cutoff = FALSE;
7491 
7492  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7493 
7494  if( violated )
7495  {
7496  /* insert LP row as cut */
7497  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7498  (*ncuts)++;
7499  }
7500  else if( !SCIPconsIsModifiable(cons) && separatecards )
7501  {
7502  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7503  if( !separateall && sol == NULL )
7504  {
7505  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7506  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7507  {
7508  SCIP_Real dualsol;
7509 
7510  dualsol = SCIProwGetDualsol(consdata->row);
7511  if( SCIPisFeasNegative(scip, dualsol) )
7512  {
7513  if( !SCIPisInfinity(scip, consdata->rhs) )
7514  {
7515  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7516  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7517  }
7518  }
7519  else if( SCIPisFeasPositive(scip, dualsol) )
7520  {
7521  if( !SCIPisInfinity(scip, -consdata->lhs) )
7522  {
7523  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7524  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7525  }
7526  }
7527  }
7528  }
7529  else
7530  {
7531  if( !SCIPisInfinity(scip, consdata->rhs) )
7532  {
7533  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7534  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7535  }
7536  if( !SCIPisInfinity(scip, -consdata->lhs) )
7537  {
7538  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7539  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7540  }
7541  }
7542  }
7543 
7544  if( *ncuts > oldncuts )
7545  {
7546  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7547  }
7548 
7549  return SCIP_OKAY;
7550 }
7551 
7552 /** propagation method for linear constraints */
7553 static
7555  SCIP* scip, /**< SCIP data structure */
7556  SCIP_CONS* cons, /**< linear constraint */
7557  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7558  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7559  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7560  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7561  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7562  int* nchgbds /**< pointer to count the total number of tightened bounds */
7563  )
7564 {
7565  SCIP_CONSDATA* consdata;
7566  SCIP_Real minactivity;
7567  SCIP_Real maxactivity;
7568  SCIP_Bool minactisrelax;
7569  SCIP_Bool maxactisrelax;
7570 
7571  assert(scip != NULL);
7572  assert(cons != NULL);
7573  assert(cutoff != NULL);
7574  assert(nchgbds != NULL);
7575 
7576  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7577 
7578  consdata = SCIPconsGetData(cons);
7579  assert(consdata != NULL);
7580 
7581  if( consdata->eventdata == NULL )
7582  {
7583  SCIP_CONSHDLR* conshdlr;
7584  SCIP_CONSHDLRDATA* conshdlrdata;
7585 
7586  conshdlr = SCIPconsGetHdlr(cons);
7587  assert(conshdlr != NULL);
7588 
7589  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7590  assert(conshdlrdata != NULL);
7591 
7592  /* catch bound change events of variables */
7593  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7594  assert(consdata->eventdata != NULL);
7595  }
7596 
7597  *cutoff = FALSE;
7598 
7599  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7600  if( !SCIPconsIsModifiable(cons) )
7601  {
7602  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7603  if( !SCIPinRepropagation(scip) )
7604  {
7605  SCIP_CALL( SCIPincConsAge(scip, cons) );
7606  }
7607 
7608  /* tighten the variable's bounds */
7609  if( tightenbounds )
7610  {
7611  int oldnchgbds;
7612 
7613  oldnchgbds = *nchgbds;
7614 
7615  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7616 
7617  if( *nchgbds > oldnchgbds )
7618  {
7619  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7620  }
7621  }
7622 
7623  /* propagate ranged rows */
7624  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7625  {
7626  int nfixedvars;
7627  int naddconss;
7628  /* cppcheck-suppress unassignedVariable */
7629  int oldnchgbds;
7630 
7631  nfixedvars = 0;
7632  naddconss = 0;
7633  SCIPdebug( oldnchgbds = *nchgbds; )
7634 
7635  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7636 
7637  if( *cutoff )
7638  {
7639  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7640  }
7641  else
7642  {
7643  SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars);
7644  }
7645 
7646  if( nfixedvars > 0 )
7647  *nchgbds += 2*nfixedvars;
7648  }
7649 
7650  /* check constraint for infeasibility and redundancy */
7651  if( !(*cutoff) )
7652  {
7653  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7654 
7655  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7656  {
7657  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7658  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7659 
7660  /* analyze conflict */
7661  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7662 
7663  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7664  *cutoff = TRUE;
7665  }
7666  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7667  {
7668  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7669  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7670 
7671  /* analyze conflict */
7672  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7673 
7674  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7675  *cutoff = TRUE;
7676  }
7677  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7678  {
7679  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7680  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7681 
7682  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7683  if( consdata->nvars > 0 )
7684  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7685  else
7686  SCIP_CALL( SCIPdelCons(scip, cons) );
7687  }
7688  }
7689  }
7690 
7691  return SCIP_OKAY;
7692 }
7693 
7694 
7695 /*
7696  * Presolving methods
7697  */
7698 
7699 /** converts all variables with fixed domain into FIXED variables */
7700 static
7702  SCIP* scip, /**< SCIP data structure */
7703  SCIP_CONS* cons, /**< linear constraint */
7704  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7705  int* nfixedvars /**< pointer to count the total number of fixed variables */
7706  )
7707 {
7708  SCIP_CONSDATA* consdata;
7709  SCIP_VAR* var;
7710  SCIP_VARSTATUS varstatus;
7711  SCIP_Real lb;
7712  SCIP_Real ub;
7713  SCIP_Bool fixed;
7714  SCIP_Bool infeasible;
7715  int v;
7716 
7717  assert(scip != NULL);
7718  assert(cons != NULL);
7719  assert(cutoff != NULL);
7720  assert(nfixedvars != NULL);
7721 
7722  consdata = SCIPconsGetData(cons);
7723  assert(consdata != NULL);
7724 
7725  for( v = 0; v < consdata->nvars; ++v )
7726  {
7727  assert(consdata->vars != NULL);
7728  var = consdata->vars[v];
7729  varstatus = SCIPvarGetStatus(var);
7730 
7731  if( varstatus != SCIP_VARSTATUS_FIXED )
7732  {
7733  lb = SCIPvarGetLbGlobal(var);
7734  ub = SCIPvarGetUbGlobal(var);
7735  if( SCIPisEQ(scip, lb, ub) )
7736  {
7737  SCIP_Real fixval;
7738 
7739  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7740  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7741  SCIPvarGetName(var), lb, ub, fixval);
7742  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7743  if( infeasible )
7744  {
7745  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7746  *cutoff = TRUE;
7747  return SCIP_OKAY;
7748  }
7749  if( fixed )
7750  (*nfixedvars)++;
7751  }
7752  }
7753  }
7754 
7755  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7756 
7757  if( infeasible )
7758  {
7759  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7760  *cutoff = TRUE;
7761  return SCIP_OKAY;
7762  }
7763 
7764  assert(consdata->removedfixings);
7765 
7766  return SCIP_OKAY;
7767 }
7768 
7769 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7770 
7771 /** extracts cliques of the constraint and adds them to SCIP
7772  *
7773  * The following clique extraction mechanism are implemeneted
7774  *
7775  * 1. collect binary variables and sort them in non increasing order, then
7776  *
7777  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7778  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7779  * condition
7780  *
7781  * minactivity + vals[i] + vals[i+1] > rhs
7782  *
7783  * and also add the binary to binary implication also for non-successive variables for which the same argument
7784  * holds
7785  *
7786  * minactivity + vals[i] + vals[j] > rhs
7787  *
7788  * 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
7789  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7790  *
7791  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7792  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7793  * condition
7794  *
7795  * maxactivity + vals[i] + vals[i-1] < lhs
7796  *
7797  * and also add the binary to binary implication also for non-successive variables for which the same argument
7798  * holds
7799  *
7800  * maxactivity + vals[i] + vals[j] < lhs
7801  *
7802  * e.g. you could multiply the above example by -1
7803  *
7804  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7805  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7806  * condition
7807  *
7808  * minactivity - vals[i] - vals[i-1] > rhs
7809  *
7810  * and also add the binary to binary implication also for non-successive variables for which the
7811  * same argument holds
7812  *
7813  * minactivity - vals[i] - vals[j] > rhs
7814  *
7815  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7816  * implication x1 = 0 => x3 = 1
7817  *
7818  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7819  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7820  * condition
7821  *
7822  * maxactivity - vals[i] - vals[i+1] < lhs
7823  *
7824  * and also add the binary to binary implication also for non-successive variables for which the same argument
7825  * holds
7826  *
7827  * maxactivity - vals[i] - vals[j] < lhs
7828  *
7829  * e.g. you could multiply the above example by -1
7830  *
7831  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7832  * as clique, (this part is done at the end of the method)
7833  *
7834  */
7835 static
7837  SCIP* scip, /**< SCIP data structure */
7838  SCIP_CONS* cons, /**< linear constraint */
7839  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7840  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7841  int* nfixedvars, /**< pointer to count number of fixed variables */
7842  int* nchgbds, /**< pointer to count the total number of tightened bounds */
7843  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7844  )
7845 {
7846  SCIP_VAR** vars;
7847  SCIP_Real* vals;
7848  SCIP_CONSDATA* consdata;
7849  SCIP_Bool lhsclique;
7850  SCIP_Bool rhsclique;
7851  SCIP_Bool finitelhs;
7852  SCIP_Bool finiterhs;
7853  SCIP_Bool finiteminact;
7854  SCIP_Bool finitemaxact;
7855  SCIP_Bool finitenegminact;
7856  SCIP_Bool finitenegmaxact;
7857  SCIP_Bool finiteposminact;
7858  SCIP_Bool finiteposmaxact;
7859  SCIP_Bool infeasible;
7860  SCIP_Bool stopped;
7861  int cliquenonzerosadded;
7862  int v;
7863  int i;
7864  int nposcoefs;
7865  int nnegcoefs;
7866  int nvars;
7867 
7868  assert(scip != NULL);
7869  assert(cons != NULL);
7870  assert(nfixedvars != NULL);
7871  assert(nchgbds != NULL);
7872  assert(cutoff != NULL);
7873  assert(!SCIPconsIsDeleted(cons));
7874 
7875  consdata = SCIPconsGetData(cons);
7876  assert(consdata != NULL);
7877 
7878  if( consdata->nvars < 2 )
7879  return SCIP_OKAY;
7880 
7881  /* add implications if posibble
7882  *
7883  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7884  * maximal absolute contribution and also only if this variable would force all other variables to their bound
7885  * corresponding to the global minimal activity of the constraint
7886  */
7887  if( !consdata->implsadded )
7888  {
7889  /* sort variables by variable type */
7890  SCIP_CALL( consdataSort(scip, consdata) );
7891 
7892  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7893  * up front, might change sorting correspondingly
7894  */
7895  /* fast abort if no binaries exist */
7896  if( !SCIPvarIsBinary(consdata->vars[0]) )
7897  return SCIP_OKAY;
7898 
7899  nvars = consdata->nvars;
7900  vars = consdata->vars;
7901  vals = consdata->vals;
7902 
7903  /* recompute activities if needed */
7904  if( !consdata->validactivities )
7905  consdataCalcActivities(scip, consdata);
7906  assert(consdata->validactivities);
7907 
7908  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7909  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7910  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7911  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7912  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7913  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7914  finiteminact = (finitenegminact && finiteposminact);
7915  finitemaxact = (finitenegmaxact && finiteposmaxact);
7916 
7917  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7918  {
7919  SCIP_Real maxabscontrib = -1.0;
7920  SCIP_Bool posval = FALSE;
7921  SCIP_Bool allbinary = TRUE;
7922  int oldnchgbds = *nchgbds;
7923  int nbdchgs = 0;
7924  int nimpls = 0;
7925  int position = -1;
7926 
7927  /* we need a valid minimal/maximal activity to add cliques */
7928  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
7929  {
7930  consdataRecomputeGlbMinactivity(scip, consdata);
7931  assert(consdata->validglbminact);
7932  }
7933 
7934  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
7935  {
7936  consdataRecomputeGlbMaxactivity(scip, consdata);
7937  assert(consdata->validglbmaxact);
7938  }
7939  assert(consdata->validglbminact || consdata->validglbmaxact);
7940 
7941  /* @todo extend this to local/constraint probing */
7942 
7943  /* determine maximal contribution to the activity */
7944  for( v = nvars - 1; v >= 0; --v )
7945  {
7946  if( SCIPvarIsBinary(vars[v]) )
7947  {
7948  if( vals[v] > 0 )
7949  {
7950  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
7951 
7952  if( value > maxabscontrib )
7953  {
7954  maxabscontrib = value;
7955  position = v;
7956  posval = TRUE;
7957  }
7958  }
7959  else
7960  {
7961  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
7962 
7963  value = REALABS(value);
7964 
7965  if( value > maxabscontrib )
7966  {
7967  maxabscontrib = value;
7968  position = v;
7969  posval = FALSE;
7970  }
7971  }
7972  }
7973  else
7974  allbinary = FALSE;
7975  }
7976  assert(0 <= position && position < nvars);
7977 
7978  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
7979  {
7980  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
7981  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7982  * implications
7983  */
7984  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
7985  {
7986  for( v = nvars - 1; v >= 0; --v )
7987  {
7988  /* binary to binary implications will be collected when extrating cliques */
7989  if( !SCIPvarIsBinary(vars[v]) )
7990  {
7991  if( v != position )
7992  {
7993  if( vals[v] > 0 )
7994  {
7995  /* add implications */
7996  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
7997  ++nimpls;
7998  *nchgbds += nbdchgs;
7999  }
8000  else
8001  {
8002  /* add implications */
8003  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8004  ++nimpls;
8005  *nchgbds += nbdchgs;
8006  }
8007 
8008  if( infeasible )
8009  {
8010  *cutoff = TRUE;
8011  break;
8012  }
8013  }
8014  }
8015  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8016  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8017  break;
8018  }
8019  }
8020 
8021  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8022  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8023  * implications
8024  */
8025  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
8026  {
8027  for( v = nvars - 1; v >= 0; --v )
8028  {
8029  /* binary to binary implications will be collected when extrating cliques */
8030  if( !SCIPvarIsBinary(vars[v]) )
8031  {
8032  if( v != position )
8033  {
8034  if( vals[v] > 0 )
8035  {
8036  /* add implications */
8037  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8038  ++nimpls;
8039  *nchgbds += nbdchgs;
8040  }
8041  else
8042  {
8043  /* add implications */
8044  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8045  ++nimpls;
8046  *nchgbds += nbdchgs;
8047  }
8048 
8049  if( infeasible )
8050  {
8051  *cutoff = TRUE;
8052  break;
8053  }
8054  }
8055  }
8056  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8057  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8058  break;
8059  }
8060  }
8061 
8062  /* did we find some implications */
8063  if( nimpls > 0 )
8064  {
8065  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8066 
8067  if( *cutoff )
8068  return SCIP_OKAY;
8069 
8070  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8071  if( *nchgbds - oldnchgbds > 0 )
8072  {
8073  /* check for fixed variables */
8074  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8075  if( *cutoff )
8076  return SCIP_OKAY;
8077 
8078  /* tighten variable's bounds */
8079  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8080  if( *cutoff )
8081  return SCIP_OKAY;
8082 
8083  /* check for fixed variables */
8084  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8085  if( *cutoff )
8086  return SCIP_OKAY;
8087  }
8088  }
8089  }
8090  }
8091 
8092  consdata->implsadded = TRUE;
8093  }
8094 
8095  /* check if we already added the cliques of this constraint */
8096  if( consdata->cliquesadded )
8097  return SCIP_OKAY;
8098 
8099  consdata->cliquesadded = TRUE;
8100  cliquenonzerosadded = 0;
8101  stopped = FALSE;
8102 
8103  /* sort variables by variable type */
8104  SCIP_CALL( consdataSort(scip, consdata) );
8105 
8106  nvars = consdata->nvars;
8107  vars = consdata->vars;
8108  vals = consdata->vals;
8109 
8110  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8111 
8112  /* recompute activities if needed */
8113  if( !consdata->validactivities )
8114  consdataCalcActivities(scip, consdata);
8115  assert(consdata->validactivities);
8116 
8117  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8118  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8119  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8120  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8121  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8122  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8123  finiteminact = (finitenegminact && finiteposminact);
8124  finitemaxact = (finitenegmaxact && finiteposmaxact);
8125 
8126  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8127  * information
8128  */
8129  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8130  {
8131  SCIP_VAR** binvars;
8132  SCIP_Real* binvarvals;
8133  int nposbinvars = 0;
8134  int nnegbinvars = 0;
8135  int allonebinary = 0;
8136 
8137  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8138  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8139 
8140  /* collect binary variables */
8141  for( i = 0; i < nvars; ++i )
8142  {
8143  if( SCIPvarIsBinary(vars[i]) )
8144  {
8145  assert(!SCIPisZero(scip, vals[i]));
8146 
8147  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8148  ++allonebinary;
8149 
8150  binvars[nposbinvars + nnegbinvars] = vars[i];
8151  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8152 
8153  if( SCIPisPositive(scip, vals[i]) )
8154  ++nposbinvars;
8155  else
8156  ++nnegbinvars;
8157 
8158  assert(nposbinvars + nnegbinvars <= nvars);
8159  }
8160  /* stop searching for binary variables, because the constraint data is sorted */
8161  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8162  break;
8163  }
8164  assert(nposbinvars + nnegbinvars <= nvars);
8165 
8166  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8167  * cliques
8168  */
8169  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8170  {
8171  SCIP_Real threshold;
8172  int oldnchgbds = *nchgbds;
8173  int nbdchgs;
8174  int jstart;
8175  int j;
8176 
8177  /* we need a valid minimal/maximal activity to add cliques */
8178  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8179  {
8180  consdataRecomputeGlbMinactivity(scip, consdata);
8181  assert(consdata->validglbminact);
8182  }
8183 
8184  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8185  {
8186  consdataRecomputeGlbMaxactivity(scip, consdata);
8187  assert(consdata->validglbmaxact);
8188  }
8189  assert(consdata->validglbminact || consdata->validglbmaxact);
8190 
8191  /* sort coefficients non-increasing to be faster in the clique search */
8192  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8193 
8194  /* case a) */
8195  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8196  {
8197  /* compute value that needs to be exceeded */
8198  threshold = consdata->rhs - consdata->glbminactivity;
8199 
8200  i = 0;
8201  j = i + 1;
8202 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8203  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8204  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
8205 #endif
8206  /* check if at least two variables are in a clique */
8207  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
8208  {
8209  ++j;
8210  /* check for extending the clique */
8211  while( j < nposbinvars )
8212  {
8213  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8214  break;
8215  ++j;
8216  }
8217  assert(j >= 2);
8218 
8219  /* add clique with at least two variables */
8220  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, FALSE, &infeasible, &nbdchgs) );
8221 
8222  if( infeasible )
8223  *cutoff = TRUE;
8224 
8225  *nchgbds += nbdchgs;
8226 
8227  cliquenonzerosadded += j;
8228  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8229  stopped = TRUE;
8230 
8231  /* exchange the last variable in the clique if possible and add all new ones */
8232  if( !stopped && !(*cutoff) && j < nposbinvars )
8233  {
8234  SCIP_VAR** clqvars;
8235  int lastfit = j - 2;
8236  assert(lastfit >= i);
8237 
8238  /* copy all 'main'-clique variables */
8239  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8240 
8241  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8242  while( lastfit >= i && j < nposbinvars )
8243  {
8244  /* check if two variables are in a clique */
8245  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8246  {
8247  clqvars[lastfit + 1] = binvars[j];
8248 
8249  /* add clique with at least two variables */
8250  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8251 
8252  if( infeasible )
8253  {
8254  *cutoff = TRUE;
8255  break;
8256  }
8257 
8258  *nchgbds += nbdchgs;
8259 
8260  cliquenonzerosadded += (lastfit - i + 2);
8261  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8262  {
8263  stopped = TRUE;
8264  break;
8265  }
8266 
8267  ++j;
8268  }
8269  else
8270  --lastfit;
8271  }
8272 
8273  SCIPfreeBufferArray(scip, &clqvars);
8274  }
8275  }
8276  }
8277 
8278  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8279  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8280  {
8281  /* check for fixed variables */
8282  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8283 
8284  if( !*cutoff )
8285  {
8286  /* tighten variable's bounds */
8287  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8288 
8289  if( !*cutoff )
8290  {
8291  /* check for fixed variables */
8292  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8293 
8294  if( !*cutoff )
8295  {
8296  /* sort variables by variable type */
8297  SCIP_CALL( consdataSort(scip, consdata) );
8298 
8299  /* recompute activities if needed */
8300  if( !consdata->validactivities )
8301  consdataCalcActivities(scip, consdata);
8302  assert(consdata->validactivities);
8303 
8304  nvars = consdata->nvars;
8305  vars = consdata->vars;
8306  vals = consdata->vals;
8307  nposbinvars = 0;
8308  nnegbinvars = 0;
8309  allonebinary = 0;
8310 
8311  /* update binary variables */
8312  for( i = 0; i < nvars; ++i )
8313  {
8314  if( SCIPvarIsBinary(vars[i]) )
8315  {
8316  assert(!SCIPisZero(scip, vals[i]));
8317 
8318  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8319  ++allonebinary;
8320 
8321  binvars[nposbinvars + nnegbinvars] = vars[i];
8322  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8323 
8324  if( SCIPisPositive(scip, vals[i]) )
8325  ++nposbinvars;
8326  else
8327  ++nnegbinvars;
8328 
8329  assert(nposbinvars + nnegbinvars <= nvars);
8330  }
8331  /* stop searching for binary variables, because the constraint data is sorted */
8332  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8333  break;
8334  }
8335  assert(nposbinvars + nnegbinvars <= nvars);
8336  }
8337  }
8338  }
8339 
8340  oldnchgbds = *nchgbds;
8341  }
8342 
8343  /* case b) */
8344  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8345  {
8346  /* compute value that needs to be deceeded */
8347  threshold = consdata->lhs - consdata->glbmaxactivity;
8348 
8349  i = nposbinvars + nnegbinvars - 1;
8350  j = i - 1;
8351 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8352  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8353  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8354 #endif
8355  /* check if two variables are in a clique */
8356  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8357  {
8358  --j;
8359  /* check for extending the clique */
8360  while( j >= nposbinvars )
8361  {
8362  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8363  break;
8364  --j;
8365  }
8366  jstart = j;
8367 
8368  assert(i - j >= 2);
8369  /* add clique with at least two variables */
8370  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8371 
8372  if( infeasible )
8373  *cutoff = TRUE;
8374 
8375  *nchgbds += nbdchgs;
8376 
8377  cliquenonzerosadded += (i - j);
8378  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8379  stopped = TRUE;
8380 
8381  /* exchange the last variable in the clique if possible and add all new ones */
8382  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8383  {
8384  SCIP_VAR** clqvars;
8385  int lastfit = jstart + 1;
8386  assert(lastfit < i);
8387 
8388  /* copy all 'main'-clique variables */
8389  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8390  ++lastfit;
8391 
8392  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8393  while( lastfit <= i && j >= nposbinvars )
8394  {
8395  /* check if two variables are in a clique */
8396  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8397  {
8398  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8399  clqvars[lastfit - jstart - 2] = binvars[j];
8400 
8401  assert(i - lastfit + 2 >= 2);
8402  /* add clique with at least two variables */
8403  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8404 
8405  if( infeasible )
8406  {
8407  *cutoff = TRUE;
8408  break;
8409  }
8410 
8411  *nchgbds += nbdchgs;
8412 
8413  cliquenonzerosadded += (i - lastfit + 2);
8414  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8415  {
8416  stopped = TRUE;
8417  break;
8418  }
8419 
8420  --j;
8421  }
8422  else
8423  ++lastfit;
8424  }
8425 
8426  SCIPfreeBufferArray(scip, &clqvars);
8427  }
8428  }
8429  }
8430 
8431  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8432  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8433  {
8434  /* check for fixed variables */
8435  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8436 
8437  if( !*cutoff )
8438  {
8439  /* tighten variable's bounds */
8440  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8441 
8442  if( !*cutoff )
8443  {
8444  /* check for fixed variables */
8445  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8446 
8447  if( !*cutoff )
8448  {
8449  /* sort variables by variable type */
8450  SCIP_CALL( consdataSort(scip, consdata) );
8451 
8452  /* recompute activities if needed */
8453  if( !consdata->validactivities )
8454  consdataCalcActivities(scip, consdata);
8455  assert(consdata->validactivities);
8456 
8457  nvars = consdata->nvars;
8458  vars = consdata->vars;
8459  vals = consdata->vals;
8460  nposbinvars = 0;
8461  nnegbinvars = 0;
8462  allonebinary = 0;
8463 
8464  /* update binary variables */
8465  for( i = 0; i < nvars; ++i )
8466  {
8467  if( SCIPvarIsBinary(vars[i]) )
8468  {
8469  assert(!SCIPisZero(scip, vals[i]));
8470 
8471  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8472  ++allonebinary;
8473 
8474  binvars[nposbinvars + nnegbinvars] = vars[i];
8475  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8476 
8477  if( SCIPisPositive(scip, vals[i]) )
8478  ++nposbinvars;
8479  else
8480  ++nnegbinvars;
8481 
8482  assert(nposbinvars + nnegbinvars <= nvars);
8483  }
8484  /* stop searching for binary variables, because the constraint data is sorted */
8485  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8486  break;
8487  }
8488  assert(nposbinvars + nnegbinvars <= nvars);
8489  }
8490  }
8491  }
8492 
8493  oldnchgbds = *nchgbds;
8494  }
8495 
8496  /* case c) */
8497  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8498  {
8499  SCIP_Bool* values;
8500 
8501  /* initialize clique values array for adding a negated clique */
8502  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8503  BMSclearMemoryArray(values, nnegbinvars);
8504 
8505  /* compute value that needs to be exceeded */
8506  threshold = consdata->rhs - consdata->glbminactivity;
8507 
8508  i = nposbinvars + nnegbinvars - 1;
8509  j = i - 1;
8510 
8511 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8512  /* check if the variable should not have already been fixed to one */
8513  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8514 #endif
8515 
8516  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8517  {
8518  --j;
8519  /* check for extending the clique */
8520  while( j >= nposbinvars )
8521  {
8522  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8523  break;
8524  --j;
8525  }
8526  jstart = j;
8527 
8528  assert(i - j >= 2);
8529  /* add negated clique with at least two variables */
8530  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8531 
8532  if( infeasible )
8533  *cutoff = TRUE;
8534 
8535  *nchgbds += nbdchgs;
8536 
8537  cliquenonzerosadded += (i - j);
8538  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8539  stopped = TRUE;
8540 
8541  /* exchange the last variable in the clique if possible and add all new ones */
8542  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8543  {
8544  SCIP_VAR** clqvars;
8545  int lastfit = j + 1;
8546  assert(lastfit < i);
8547 
8548  /* copy all 'main'-clique variables */
8549  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8550  ++lastfit;
8551 
8552  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8553  while( lastfit <= i && j >= nposbinvars )
8554  {
8555  /* check if two variables are in a negated clique */
8556  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8557  {
8558  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8559  clqvars[lastfit - jstart - 2] = binvars[j];
8560 
8561  assert(i - lastfit + 2 >= 2);
8562  /* add clique with at least two variables */
8563  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8564 
8565  if( infeasible )
8566  {
8567  *cutoff = TRUE;
8568  break;
8569  }
8570 
8571  *nchgbds += nbdchgs;
8572 
8573  cliquenonzerosadded += (i - lastfit + 2);
8574  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8575  {
8576  stopped = TRUE;
8577  break;
8578  }
8579 
8580  --j;
8581  }
8582  else
8583  ++lastfit;
8584  }
8585 
8586  SCIPfreeBufferArray(scip, &clqvars);
8587  }
8588  }
8589 
8590  SCIPfreeBufferArray(scip, &values);
8591  }
8592 
8593  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8594  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8595  {
8596  /* check for fixed variables */
8597  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8598 
8599  if( !*cutoff )
8600  {
8601  /* tighten variable's bounds */
8602  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8603 
8604  if( !*cutoff )
8605  {
8606  /* check for fixed variables */
8607  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8608 
8609  if( !*cutoff )
8610  {
8611  /* sort variables by variable type */
8612  SCIP_CALL( consdataSort(scip, consdata) );
8613 
8614  /* recompute activities if needed */
8615  if( !consdata->validactivities )
8616  consdataCalcActivities(scip, consdata);
8617  assert(consdata->validactivities);
8618 
8619  nvars = consdata->nvars;
8620  vars = consdata->vars;
8621  vals = consdata->vals;
8622  nposbinvars = 0;
8623  nnegbinvars = 0;
8624  allonebinary = 0;
8625 
8626  /* update binary variables */
8627  for( i = 0; i < nvars; ++i )
8628  {
8629  if( SCIPvarIsBinary(vars[i]) )
8630  {
8631  assert(!SCIPisZero(scip, vals[i]));
8632 
8633  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8634  ++allonebinary;
8635 
8636  binvars[nposbinvars + nnegbinvars] = vars[i];
8637  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8638 
8639  if( SCIPisPositive(scip, vals[i]) )
8640  ++nposbinvars;
8641  else
8642  ++nnegbinvars;
8643 
8644  assert(nposbinvars + nnegbinvars <= nvars);
8645  }
8646  /* stop searching for binary variables, because the constraint data is sorted */
8647  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8648  break;
8649  }
8650  assert(nposbinvars + nnegbinvars <= nvars);
8651  }
8652  }
8653  }
8654  }
8655 
8656  /* case d) */
8657  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8658  {
8659  SCIP_Bool* values;
8660 
8661  /* initialize clique values array for adding a negated clique */
8662  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8663  BMSclearMemoryArray(values, nposbinvars);
8664 
8665  /* compute value that needs to be exceeded */
8666  threshold = consdata->lhs - consdata->glbmaxactivity;
8667 
8668  i = 0;
8669  j = i + 1;
8670 
8671 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8672  /* check if the variable should not have already been fixed to one */
8673  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
8674 #endif
8675 
8676  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8677  {
8678  ++j;
8679  /* check for extending the clique */
8680  while( j < nposbinvars )
8681  {
8682  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8683  break;
8684  ++j;
8685  }
8686  assert(j >= 2);
8687 
8688  /* add negated clique with at least two variables */
8689  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, FALSE, &infeasible, &nbdchgs) );
8690 
8691  if( infeasible )
8692  *cutoff = TRUE;
8693 
8694  *nchgbds += nbdchgs;
8695 
8696  cliquenonzerosadded += j;
8697  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8698  stopped = TRUE;
8699 
8700  /* exchange the last variable in the clique if possible and add all new ones */
8701  if( !stopped && !(*cutoff) && j < nposbinvars )
8702  {
8703  SCIP_VAR** clqvars;
8704  int lastfit = j - 2;
8705  assert(lastfit >= i);
8706 
8707  /* copy all 'main'-clique variables */
8708  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8709 
8710  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8711  while( lastfit >= i && j < nposbinvars )
8712  {
8713  /* check if two variables are in a negated clique */
8714  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8715  {
8716  clqvars[lastfit + 1] = binvars[j];
8717 
8718  /* add clique with at least two variables */
8719  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8720 
8721  if( infeasible )
8722  {
8723  *cutoff = TRUE;
8724  break;
8725  }
8726 
8727  *nchgbds += nbdchgs;
8728 
8729  cliquenonzerosadded += (lastfit - i + 2);
8730  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8731  break;
8732 
8733  ++j;
8734  }
8735  else
8736  --lastfit;
8737  }
8738 
8739  SCIPfreeBufferArray(scip, &clqvars);
8740  }
8741  }
8742 
8743  SCIPfreeBufferArray(scip, &values);
8744  }
8745  }
8746 
8747  SCIPfreeBufferArray(scip, &binvarvals);
8748  SCIPfreeBufferArray(scip, &binvars);
8749 
8750  if( *cutoff )
8751  return SCIP_OKAY;
8752  }
8753 
8754  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8755 
8756  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8757  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8758  */
8759  nposcoefs = 0;
8760  nnegcoefs = 0;
8761  for( i = 0; i < nvars; ++i )
8762  {
8763  if( !SCIPvarIsBinary(vars[i]) )
8764  return SCIP_OKAY;
8765  else if( SCIPisEQ(scip, vals[i], +1.0) )
8766  nposcoefs++;
8767  else if( SCIPisEQ(scip, vals[i], -1.0) )
8768  nnegcoefs++;
8769  else
8770  return SCIP_OKAY;
8771  }
8772 
8773  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8774  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8775 
8776  if( lhsclique || rhsclique )
8777  {
8778  SCIP_Bool* values;
8779  int nbdchgs;
8780 
8781  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8782  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8783  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8784 
8785  for( i = 0; i < nvars; ++i )
8786  values[i] = (rhsclique == (vals[i] > 0.0));
8787 
8788  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8789 
8790  if( infeasible )
8791  *cutoff = TRUE;
8792 
8793  *nchgbds += nbdchgs;
8794  SCIPfreeBufferArray(scip, &values);
8795  }
8796 
8797  return SCIP_OKAY;
8798 }
8799 
8800 /** tightens left and right hand side of constraint due to integrality */
8801 static
8803  SCIP* scip, /**< SCIP data structure */
8804  SCIP_CONS* cons, /**< linear constraint */
8805  int* nchgsides, /**< pointer to count number of side changes */
8806  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8807  )
8808 {
8809  SCIP_CONSDATA* consdata;
8810  SCIP_Real newlhs;
8811  SCIP_Real newrhs;
8812  SCIP_Bool chglhs;
8813  SCIP_Bool chgrhs;
8814  SCIP_Bool integral;
8815  int i;
8816 
8817  assert(scip != NULL);
8818  assert(cons != NULL);
8819  assert(nchgsides != NULL);
8820 
8821  consdata = SCIPconsGetData(cons);
8822  assert(consdata != NULL);
8823 
8824  *infeasible = FALSE;
8825 
8826  chglhs = FALSE;
8827  chgrhs = FALSE;
8828  newlhs = -SCIPinfinity(scip);
8829  newrhs = SCIPinfinity(scip);
8830 
8831  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8832  {
8833  integral = TRUE;
8834  for( i = 0; i < consdata->nvars && integral; ++i )
8835  {
8836  integral = SCIPisIntegral(scip, consdata->vals[i])
8837  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8838  }
8839  if( integral )
8840  {
8841  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8842  {
8843  newlhs = SCIPfeasCeil(scip, consdata->lhs);
8844  chglhs = TRUE;
8845  }
8846  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8847  {
8848  newrhs = SCIPfeasFloor(scip, consdata->rhs);
8849  chgrhs = TRUE;
8850  }
8851 
8852  /* check whether rounding would lead to an unsatisfiable constraint */
8853  if( SCIPisGT(scip, newlhs, newrhs) )
8854  {
8855  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8856  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8857 
8858  *infeasible = TRUE;
8859  return SCIP_OKAY;
8860  }
8861 
8862  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8863  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8864 
8865  if( chglhs )
8866  {
8867  assert(!SCIPisInfinity(scip, -newlhs));
8868 
8869  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8870  if( !consdata->upgraded )
8871  (*nchgsides)++;
8872  }
8873  if( chgrhs )
8874  {
8875  assert(!SCIPisInfinity(scip, newrhs));
8876 
8877  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8878  if( !consdata->upgraded )
8879  (*nchgsides)++;
8880  }
8881  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8882  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8883  }
8884  }
8885 
8886  return SCIP_OKAY;
8887 }
8888 
8889 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8890  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8891  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8892  * (i) ai >= 0:
8893  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8894  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8895  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8896  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8897  * - change coefficients:
8898  * ai' := max(lhs - minact, maxact - rhs)
8899  * lhs' := lhs - (ai - ai')*li
8900  * rhs' := rhs - (ai - ai')*ui
8901  * (ii) ai < 0:
8902  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8903  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8904  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8905  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8906  * - change coefficients:
8907  * ai' := min(rhs - maxact, minact - lhs)
8908  * lhs' := lhs - (ai - ai')*ui
8909  * rhs' := rhs - (ai - ai')*li
8910  *
8911  * We further try to remove redundant variable from the constraint;
8912  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
8913  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8914  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
8915  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
8916  * 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
8917  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
8918  *
8919  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8920  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8921  */
8922 static
8924  SCIP* scip, /**< SCIP data structure */
8925  SCIP_CONS* cons, /**< linear constraint */
8926  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8927  int* nchgsides /**< pointer to count number of side changes */
8928  )
8929 {
8930  SCIP_CONSDATA* consdata;
8931  SCIP_VAR* var;
8932  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
8933  * activity, ignoring the coefficients contributing with infinite value */
8934  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
8935  * activity, ignoring the coefficients contributing with infinite value */
8936  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
8937  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
8938  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
8939  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
8940  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
8941  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
8942  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
8943  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
8944  SCIP_Real val;
8945  SCIP_Real newval;
8946  SCIP_Real newlhs;
8947  SCIP_Real newrhs;
8948  SCIP_Real lb;
8949  SCIP_Real ub;
8950  int i;
8951 
8952  assert(scip != NULL);
8953  assert(cons != NULL);
8954  assert(nchgcoefs != NULL);
8955  assert(nchgsides != NULL);
8956 
8957  consdata = SCIPconsGetData(cons);
8958  assert(consdata != NULL);
8959 
8960  /* @todo Is this still needed with automatic recomputation of activities? */
8961  /* if the maximal coefficient is too large, recompute the activities */
8962  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
8963  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
8964  {
8965  consdataRecomputeMinactivity(scip, consdata);
8966  consdataRecomputeMaxactivity(scip, consdata);
8967  }
8968 
8969  /* get the minimal and maximal activity of the constraint */
8970  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8971 
8972  minleftactivity = 0.0;
8973  maxleftactivity = 0.0;
8974 
8975  /* try to tighten each coefficient */
8976  i = 0;
8977  while( i < consdata->nvars )
8978  {
8979  var = consdata->vars[i];
8980 
8981  /* get coefficient and variable's bounds */
8982  lb = SCIPvarGetLbLocal(var);
8983  ub = SCIPvarGetUbLocal(var);
8984  val = consdata->vals[i];
8985  assert(!SCIPisZero(scip, val));
8986 
8987  /* check sign of coefficient */
8988  if( val >= 0.0 )
8989  {
8990  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
8992  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
8993  {
8994  /* change coefficients:
8995  * ai' := max(lhs - minact, maxact - rhs)
8996  * lhs' := lhs - (ai - ai')*li
8997  * rhs' := rhs - (ai - ai')*ui
8998  */
8999 
9000  lval = consdata->lhs - minactivity;
9001  rval = maxactivity - consdata->rhs;
9002 
9003  /* Try to avoid cancellation, if there are only two variables */
9004  if( consdata->nvars == 2 )
9005  {
9006  SCIP_Real otherval;
9007  otherval = consdata->vals[1-i];
9008 
9009  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9010  {
9011  lval = consdata->lhs - val*lb;
9012  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9013  }
9014 
9015  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9016  {
9017  rval = val*ub - consdata->rhs;
9018  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9019  }
9020  }
9021 
9022  newval = MAX(lval, rval);
9023  assert(SCIPisSumRelLE(scip, newval, val));
9024 
9025  /* Try to avoid cancellation in computation of lhs/rhs */
9026  newlhs = consdata->lhs - val * lb;
9027  newlhs += newval * lb;
9028  newrhs = consdata->rhs - val * ub;
9029  newrhs += newval * ub;
9030 
9031  if( !SCIPisSumRelEQ(scip, newval, val) )
9032  {
9033  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9034  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9035  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9036 
9037  /* update the coefficient and the activity bounds */
9038  if( SCIPisZero(scip, newval) )
9039  {
9040  SCIP_CALL( delCoefPos(scip, cons, i) );
9041  i--;
9042  }
9043  else
9044  {
9045  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9046  }
9047  (*nchgcoefs)++;
9048 
9049  /* get the new minimal and maximal activity of the constraint */
9050  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9051 
9052  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9053  {
9054  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9055 
9056  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9057  (*nchgsides)++;
9058  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9059  }
9060 
9061  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9062  {
9063  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9064 
9065  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9066  (*nchgsides)++;
9067  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9068  }
9069  }
9070  }
9071  else
9072  {
9073  if( !SCIPisInfinity(scip, -minleftactivity) )
9074  {
9075  assert(!SCIPisInfinity(scip, val));
9076  assert(!SCIPisInfinity(scip, lb));
9077  if( SCIPisInfinity(scip, -lb) )
9078  minleftactivity = -SCIPinfinity(scip);
9079  else
9080  minleftactivity += val * lb;
9081  }
9082 
9083  if( !SCIPisInfinity(scip, maxleftactivity) )
9084  {
9085  assert(!SCIPisInfinity(scip, val));
9086  assert(!SCIPisInfinity(scip, -ub));
9087  if( SCIPisInfinity(scip,ub) )
9088  maxleftactivity = SCIPinfinity(scip);
9089  else
9090  maxleftactivity += val * ub;
9091  }
9092  }
9093  }
9094  else
9095  {
9096  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9098  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9099  {
9100  /* change coefficients:
9101  * ai' := min(rhs - maxact, minact - lhs)
9102  * lhs' := lhs - (ai - ai')*ui
9103  * rhs' := rhs - (ai - ai')*li
9104  */
9105 
9106  lval = minactivity - consdata->lhs;
9107  rval = consdata->rhs - maxactivity;
9108 
9109  /* Try to avoid cancellation, if there are only two variables */
9110  if( consdata->nvars == 2 )
9111  {
9112  SCIP_Real otherval;
9113  otherval = consdata->vals[1-i];
9114 
9115  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9116  {
9117  lval = val*ub - consdata->lhs;
9118  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9119  }
9120 
9121  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9122  {
9123  rval = consdata->rhs - val*lb;
9124  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9125  }
9126  }
9127 
9128  newval = MIN(lval, rval);
9129  assert(SCIPisSumRelGE(scip, newval, val));
9130 
9131  /* Try to avoid cancellation in computation of lhs/rhs */
9132  newlhs = consdata->lhs - val * ub;
9133  newlhs += newval * ub;
9134  newrhs = consdata->rhs - val * lb;
9135  newrhs += newval * lb;
9136 
9137  if( !SCIPisSumRelEQ(scip, newval, val) )
9138  {
9139  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9140  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9141  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9142 
9143  /* update the coefficient and the activity bounds */
9144  if( SCIPisZero(scip, newval) )
9145  {
9146  SCIP_CALL( delCoefPos(scip, cons, i) );
9147  i--;
9148  }
9149  else
9150  {
9151  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9152  }
9153  (*nchgcoefs)++;
9154 
9155  /* get the new minimal and maximal activity of the constraint */
9156  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9157 
9158  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9159  {
9160  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9161 
9162  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9163  (*nchgsides)++;
9164  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9165  }
9166 
9167  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9168  {
9169  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9170 
9171  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9172  (*nchgsides)++;
9173  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9174  }
9175  }
9176  }
9177  else
9178  {
9179  if( !SCIPisInfinity(scip, -minleftactivity) )
9180  {
9181  assert(!SCIPisInfinity(scip, -val));
9182  assert(!SCIPisInfinity(scip, -ub));
9183  if( SCIPisInfinity(scip, ub) )
9184  minleftactivity = -SCIPinfinity(scip);
9185  else
9186  minleftactivity += val * ub;
9187  }
9188 
9189  if( !SCIPisInfinity(scip, maxleftactivity) )
9190  {
9191  assert(!SCIPisInfinity(scip, -val));
9192  assert(!SCIPisInfinity(scip, lb));
9193  if( SCIPisInfinity(scip, -lb) )
9194  maxleftactivity = SCIPinfinity(scip);
9195  else
9196  maxleftactivity += val * lb;
9197  }
9198  }
9199  }
9200  ++i;
9201  }
9202 
9203  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9204  minleftactivity, consdata->rhs);
9205  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9206  maxleftactivity, consdata->lhs);
9207 
9208  /* minleft == \infty ==> minactivity == \infty */
9209  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9210  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9211 
9212  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9213  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9214  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9215  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9216  */
9217  assert(!SCIPisInfinity(scip, minactivity));
9218  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9219  return SCIP_OKAY;
9220 
9221  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9222  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9223  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9224  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9225  */
9226  assert(!SCIPisInfinity(scip, -maxactivity));
9227  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9228  return SCIP_OKAY;
9229 
9230  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9231  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9232  */
9233  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9234  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9235 
9236  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9237  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9238  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9239  * they can be removed from the constraint.
9240  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9241  */
9242  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9243  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9244  {
9245  SCIP_Real minleftactivitypart;
9246  SCIP_Real maxleftactivitypart;
9247 
9248  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9249 
9250  /* try to remove redundant variables from constraint */
9251  i = 0;
9252  while( i < consdata->nvars )
9253  {
9254  var = consdata->vars[i];
9255  minleftactivitypart = 0.0;
9256  maxleftactivitypart = 0.0;
9257  lb = SCIPvarGetLbLocal(var);
9258  ub = SCIPvarGetUbLocal(var);
9259 
9260  /* get coefficient and variable's bounds */
9261  val = consdata->vals[i];
9262  assert(!SCIPisZero(scip, val));
9263 
9264  /* check sign of coefficient */
9265  if( val >= 0.0 )
9266  {
9267  /* negation of condition above in case of positive val */
9268  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9269  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9270  {
9271  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9272  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9273  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9274  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9275 
9276  minleftactivitypart = val * lb;
9277  maxleftactivitypart = val * ub;
9278 
9279  SCIP_CALL( delCoefPos(scip, cons, i) );
9280  i--;
9281 
9282  /* get the new minimal and maximal activity of the constraint */
9283  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9284 
9285  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9286  * huge contributions
9287  */
9288  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9289  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9290  }
9291  }
9292  else
9293  {
9294  /* negation of condition above in case of negative val */
9295  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9296  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9297  {
9298  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9299  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9300 
9301  minleftactivitypart = val * ub;
9302  maxleftactivitypart = val * lb;
9303 
9304  SCIP_CALL( delCoefPos(scip, cons, i) );
9305  i--;
9306 
9307  /* get the new minimal and maximal activity of the constraint */
9308  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9309 
9310  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9311  * huge contributions
9312  */
9313  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9314  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9315  }
9316  }
9317 
9318  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9319  * redundant variables could get deleted,
9320  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9321  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9322  * we would also delete y2 and as a result we would have gotten infeasibility */
9323  /* adjust lhs and right hand side */
9324  newlhs = consdata->lhs - minleftactivitypart;
9325  newrhs = consdata->rhs - maxleftactivitypart;
9326 
9327  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9328  {
9329  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9330  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9331  ++(*nchgsides);
9332  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9333  }
9334  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9335  {
9336  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9337  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9338  ++(*nchgsides);
9339  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9340  }
9341  ++i;
9342  }
9343  }
9344 
9345  return SCIP_OKAY;
9346 }
9347 
9348 /* processes equality with only one variable by fixing the variable and deleting the constraint */
9349 static
9351  SCIP* scip, /**< SCIP data structure */
9352  SCIP_CONS* cons, /**< linear constraint */
9353  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9354  int* nfixedvars, /**< pointer to count number of fixed variables */
9355  int* ndelconss /**< pointer to count number of deleted constraints */
9356  )
9357 {
9358  SCIP_CONSDATA* consdata;
9359  SCIP_VAR* var;
9360  SCIP_Real val;
9361  SCIP_Real fixval;
9362  SCIP_Bool infeasible;
9363  SCIP_Bool fixed;
9364 
9365  assert(scip != NULL);
9366  assert(cons != NULL);
9367  assert(cutoff != NULL);
9368  assert(nfixedvars != NULL);
9369  assert(ndelconss != NULL);
9370 
9371  consdata = SCIPconsGetData(cons);
9372  assert(consdata != NULL);
9373  assert(consdata->nvars == 1);
9374  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9375 
9376  /* calculate the value to fix the variable to */
9377  var = consdata->vars[0];
9378  val = consdata->vals[0];
9379  assert(!SCIPisZero(scip, val));
9380  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9381  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9382  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9383  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9384 
9385  /* fix variable */
9386  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9387  if( infeasible )
9388  {
9389  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9390  *cutoff = TRUE;
9391  return SCIP_OKAY;
9392  }
9393  if( fixed )
9394  (*nfixedvars)++;
9395 
9396  /* disable constraint */
9397  SCIP_CALL( SCIPdelCons(scip, cons) );
9398  if( !consdata->upgraded )
9399  (*ndelconss)++;
9400 
9401  return SCIP_OKAY;
9402 }
9403 
9404 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9405 static
9407  SCIP* scip, /**< SCIP data structure */
9408  SCIP_CONS* cons, /**< linear constraint */
9409  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9410  int* naggrvars, /**< pointer to count number of aggregated variables */
9411  int* ndelconss /**< pointer to count number of deleted constraints */
9412  )
9413 {
9414  SCIP_CONSDATA* consdata;
9415  SCIP_Bool infeasible;
9416  SCIP_Bool redundant;
9417  SCIP_Bool aggregated;
9418 
9419  assert(scip != NULL);
9420  assert(cons != NULL);
9421  assert(cutoff != NULL);
9422  assert(naggrvars != NULL);
9423  assert(ndelconss != NULL);
9424 
9425  consdata = SCIPconsGetData(cons);
9426  assert(consdata != NULL);
9427  assert(consdata->nvars == 2);
9428  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9429 
9430  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9431  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9432  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9433 
9434  /* aggregate the equality */
9435  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9436  consdata->rhs, &infeasible, &redundant, &aggregated) );
9437 
9438  /* check for infeasibility of aggregation */
9439  if( infeasible )
9440  {
9441  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9442  *cutoff = TRUE;
9443  return SCIP_OKAY;
9444  }
9445 
9446  /* count the aggregation */
9447  if( aggregated )
9448  (*naggrvars)++;
9449 
9450  /* delete the constraint, if it is redundant */
9451  if( redundant )
9452  {
9453  SCIP_CALL( SCIPdelCons(scip, cons) );
9454 
9455  if( !consdata->upgraded )
9456  (*ndelconss)++;
9457  }
9458 
9459  return SCIP_OKAY;
9460 }
9461 
9462 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9463 static
9465  SCIP* scip, /**< SCIP data structure */
9466  SCIP_CONSDATA* consdata, /**< linear constraint data */
9467  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9468  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9469  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9470  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9471  )
9472 {
9473  SCIP_Real slackvarlb;
9474  SCIP_Real slackvarub;
9475 
9476  assert(scip != NULL);
9477  assert(consdata != NULL);
9478  assert(newlhs != NULL);
9479  assert(newrhs != NULL);
9480  assert(!SCIPisInfinity(scip, -consdata->lhs));
9481  assert(!SCIPisInfinity(scip, consdata->rhs));
9482 
9483  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9484  slackvarub = SCIPvarGetUbGlobal(slackvar);
9485  if( slackcoef > 0.0 )
9486  {
9487  if( SCIPisInfinity(scip, -slackvarlb) )
9488  *newrhs = SCIPinfinity(scip);
9489  else
9490  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9491  if( SCIPisInfinity(scip, slackvarub) )
9492  *newlhs = -SCIPinfinity(scip);
9493  else
9494  *newlhs = consdata->lhs - slackcoef * slackvarub;
9495  }
9496  else
9497  {
9498  if( SCIPisInfinity(scip, -slackvarlb) )
9499  *newlhs = -SCIPinfinity(scip);
9500  else
9501  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9502  if( SCIPisInfinity(scip, slackvarub) )
9503  *newrhs = SCIPinfinity(scip);
9504  else
9505  *newrhs = consdata->lhs - slackcoef * slackvarub;
9506  }
9507  assert(SCIPisLE(scip, *newlhs, *newrhs));
9508 }
9509 
9510 #define MAXMULTIAGGRQUOTIENT 1e+03
9511 
9512 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9513  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9514  * is implicitly integral by this constraint
9515  *
9516  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9517  * can help.
9518  */
9519 static
9521  SCIP* scip, /**< SCIP data structure */
9522  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9523  SCIP_CONS* cons, /**< linear constraint */
9524  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9525  int* naggrvars, /**< pointer to count number of aggregated variables */
9526  int* ndelconss /**< pointer to count number of deleted constraints */
9527  )
9528 {
9529  SCIP_CONSDATA* consdata;
9530  SCIP_VAR** vars;
9531  SCIP_Real* vals;
9532  SCIP_VARTYPE bestslacktype;
9533  SCIP_VARTYPE slacktype;
9534  SCIP_Real lhs;
9535  SCIP_Real rhs;
9536  SCIP_Real bestslackdomrng;
9537  SCIP_Real minabsval;
9538  SCIP_Real maxabsval;
9539  SCIP_Bool bestremovescons;
9540  SCIP_Bool coefszeroone;
9541  SCIP_Bool coefsintegral;
9542  SCIP_Bool varsintegral;
9543  SCIP_Bool infeasible;
9544  SCIP_Bool samevar;
9545  int supinf; /* counter for infinite contributions to the supremum of a possible
9546  * multi-aggregation
9547  */
9548  int infinf; /* counter for infinite contributions to the infimum of a possible
9549  * multi-aggregation
9550  */
9551  int maxnlocksstay;
9552  int maxnlocksremove;
9553  int bestslackpos;
9554  int bestnlocks;
9555  int ncontvars;
9556  int contvarpos;
9557  int nintvars;
9558  int nimplvars;
9559  int intvarpos;
9560  int v;
9561 
9562  assert(scip != NULL);
9563  assert(cons != NULL);
9564  assert(cutoff != NULL);
9565  assert(naggrvars != NULL);
9566 
9567  consdata = SCIPconsGetData(cons);
9568  assert(consdata != NULL);
9569  assert(consdata->nvars > 2);
9570  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9571 
9572  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9573 
9574  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9575  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9576  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9577  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9578  */
9579  lhs = consdata->lhs;
9580  rhs = consdata->rhs;
9581  maxnlocksstay = 0;
9582  if( consdata->nvars == 3 )
9583  {
9584  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9585  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9586  */
9587  maxnlocksremove = 3;
9588  }
9589  else if( consdata->nvars == 4 )
9590  {
9591  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9592  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9593  */
9594  maxnlocksremove = 2;
9595  }
9596  else
9597  {
9598  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9599  maxnlocksremove = 1;
9600  }
9601 
9602  /* the locks on this constraint can be ignored */
9603  if( SCIPconsIsChecked(cons) )
9604  {
9605  if( !SCIPisInfinity(scip, -lhs) )
9606  {
9607  maxnlocksstay++;
9608  maxnlocksremove++;
9609  }
9610  if( !SCIPisInfinity(scip, rhs) )
9611  {
9612  maxnlocksstay++;
9613  maxnlocksremove++;
9614  }
9615  }
9616 
9617  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9618  vars = consdata->vars;
9619  vals = consdata->vals;
9620  bestslackpos = -1;
9621  bestslacktype = SCIP_VARTYPE_BINARY;
9622  bestnlocks = INT_MAX;
9623  bestremovescons = FALSE;
9624  bestslackdomrng = 0.0;
9625  coefszeroone = TRUE;
9626  coefsintegral = TRUE;
9627  varsintegral = TRUE;
9628  ncontvars = 0;
9629  contvarpos = -1;
9630  nintvars = 0;
9631  nimplvars = 0;
9632  intvarpos = -1;
9633  minabsval = SCIPinfinity(scip);
9634  maxabsval = -1.0;
9635  for( v = 0; v < consdata->nvars; ++v )
9636  {
9637  SCIP_VAR* var;
9638  SCIP_Real val;
9639  SCIP_Real absval;
9640  SCIP_Real varlb;
9641  SCIP_Real varub;
9642  SCIP_Bool iscont;
9643  int nlocks;
9644 
9645  assert(vars != NULL);
9646  assert(vals != NULL);
9647 
9648  var = vars[v];
9649  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9650  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9651  varlb = SCIPvarGetLbGlobal(var);
9652  varub = SCIPvarGetUbGlobal(var);
9653 
9654  val = vals[v];
9655  absval = REALABS(val);
9656  assert(SCIPisPositive(scip, absval));
9657 
9658  /* calculate minimal and maximal absolute value */
9659  if( absval < minabsval )
9660  minabsval = absval;
9661  if( absval > maxabsval )
9662  maxabsval = absval;
9663 
9664  /* do not try to multi aggregate, when numerical bad */
9665  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
9666  return SCIP_OKAY;
9667 
9668  slacktype = SCIPvarGetType(var);
9669  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9670  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9671  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9672  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9673 
9674  /* update candidates for continuous -> implint and integer -> implint conversion */
9675  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9676  {
9677  ncontvars++;
9678  contvarpos = v;
9679  }
9680  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9681  {
9682  ++nimplvars;
9683  }
9684  else if( slacktype == SCIP_VARTYPE_INTEGER )
9685  {
9686  nintvars++;
9687  intvarpos = v;
9688  }
9689 
9690  /* check, if variable is already fixed or aggregated */
9691  if( !SCIPvarIsActive(var) )
9692  continue;
9693 
9694  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9696 
9697  if( nlocks > maxnlocksremove )
9698  continue;
9699 
9700  /* check, if variable can be used as a slack variable */
9701  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9702  !SCIPdoNotMultaggrVar(scip, var) )
9703  {
9704  SCIP_Bool better;
9705  SCIP_Bool equal;
9706  SCIP_Real slackdomrng;
9707 
9708  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9709  slackdomrng = SCIPinfinity(scip);
9710  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9711  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9712  return SCIP_OKAY;
9713  else
9714  {
9715  slackdomrng = (varub - varlb)*absval;
9716  assert(!SCIPisInfinity(scip, slackdomrng));
9717  }
9718  equal = FALSE;
9719  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9720  if( !better && slacktype == bestslacktype )
9721  {
9722  better = (nlocks < bestnlocks);
9723  if( nlocks == bestnlocks && !bestremovescons )
9724  {
9725  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9726  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9727  }
9728  }
9729 
9730  if( better || equal )
9731  {
9732  SCIP_Real minresactivity;
9733  SCIP_Real maxresactivity;
9734  SCIP_Real newlhs;
9735  SCIP_Real newrhs;
9736  SCIP_Bool removescons;
9737  SCIP_Bool minisrelax;
9738  SCIP_Bool maxisrelax;
9739  SCIP_Bool isminsettoinfinity;
9740  SCIP_Bool ismaxsettoinfinity;
9741 
9742  /* check if the constraint becomes redundant after multi-aggregation */
9743  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9744  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9745 
9746  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9747  * activity
9748  */
9749  if( minisrelax || maxisrelax )
9750  continue;
9751 
9752  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9753  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9754 
9755  /* check resactivities for reliability */
9756  if( removescons )
9757  {
9758  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9759  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9760 
9761  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9762  && SCIPisFeasLE(scip, newlhs, minresactivity))
9763  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9764 
9765  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9766  }
9767 
9768  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9769  if( conshdlrdata->multaggrremove && !removescons )
9770  continue;
9771 
9772  /* prefer variables that make the constraints redundant */
9773  if( bestremovescons && !removescons )
9774  continue;
9775 
9776  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9777  * other constraints
9778  */
9779  if( !removescons && nlocks > maxnlocksstay )
9780  continue;
9781 
9782  better = better || (!bestremovescons && removescons);
9783  if( better )
9784  {
9785  bestslackpos = v;
9786  bestslacktype = slacktype;
9787  bestnlocks = nlocks;
9788  bestslackdomrng = slackdomrng;
9789  bestremovescons = removescons;
9790  }
9791  }
9792  }
9793  }
9794 
9795  /* if all coefficients and variables are integral, the right hand side must also be integral */
9796  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9797  {
9798  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9799  SCIPdebugPrintCons(scip, cons, NULL);
9800  *cutoff = TRUE;
9801  return SCIP_OKAY;
9802  }
9803 
9804  supinf = 0;
9805  infinf = 0;
9806  samevar = FALSE;
9807 
9808  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9809  for( v = 0; v < consdata->nvars; ++v )
9810  {
9811  if( v != bestslackpos )
9812  {
9813  if( SCIPisPositive(scip, consdata->vals[v]) )
9814  {
9815  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9816  {
9817  ++supinf;
9818  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9819  {
9820  ++infinf;
9821  samevar = TRUE;
9822  }
9823  }
9824  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9825  ++infinf;
9826  }
9827  else if( SCIPisNegative(scip, consdata->vals[v]) )
9828  {
9829  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9830  {
9831  ++supinf;
9832  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9833  {
9834  ++infinf;
9835  samevar = TRUE;
9836  }
9837  }
9838  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9839  ++infinf;
9840  }
9841  }
9842  }
9843  assert(!samevar || (supinf > 0 && infinf > 0));
9844 
9845  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9846  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9847  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9848  {
9849  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9850  return SCIP_OKAY;
9851  }
9852 
9853  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9854  * we cannot aggregate the variable, because the integrality condition would get lost
9855  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9856  * loose the integrality condition for this variable.
9857  */
9858  if( bestslackpos >= 0
9859  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9860  || (coefsintegral && varsintegral && nimplvars == 0)) )
9861  {
9862  SCIP_VAR* slackvar;
9863  SCIP_Real* scalars;
9864  SCIP_Real slackcoef;
9865  SCIP_Real aggrconst;
9866  SCIP_Real newlhs;
9867  SCIP_Real newrhs;
9868  SCIP_Bool aggregated;
9869 
9870  /* we found a slack variable that only occurs in at most one other constraint:
9871  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9872  */
9873  assert(bestslackpos < consdata->nvars);
9874 
9875  /* do not multi aggregate binary variables */
9876  if( SCIPvarIsBinary(vars[bestslackpos]) )
9877  return SCIP_OKAY;
9878 
9879  /* convert equality into inequality by deleting the slack variable:
9880  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9881  */
9882  slackvar = vars[bestslackpos];
9883  slackcoef = vals[bestslackpos];
9884  assert(!SCIPisZero(scip, slackcoef));
9885  aggrconst = consdata->rhs/slackcoef;
9886 
9887  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9888  assert(SCIPisLE(scip, newlhs, newrhs));
9889  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9890  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9891  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9892 
9893  /* allocate temporary memory */
9894  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9895 
9896  /* set up the multi-aggregation */
9897  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9898  for( v = 0; v < consdata->nvars; ++v )
9899  {
9900  scalars[v] = -consdata->vals[v]/slackcoef;
9901  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9902  }
9903  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9904  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9905  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9906 
9907  /* perform the multi-aggregation */
9908  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9909  &infeasible, &aggregated) );
9910  assert(aggregated);
9911 
9912  /* free temporary memory */
9913  SCIPfreeBufferArray(scip, &scalars);
9914 
9915  /* check for infeasible aggregation */
9916  if( infeasible )
9917  {
9918  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9919  *cutoff = TRUE;
9920  return SCIP_OKAY;
9921  }
9922 
9923  (*naggrvars)++;
9924 
9925  /* delete the constraint if it became redundant */
9926  if( bestremovescons )
9927  {
9928  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9929  SCIP_CALL( SCIPdelCons(scip, cons) );
9930 
9931  if( !consdata->upgraded )
9932  (*ndelconss)++;
9933  }
9934  }
9935  else if( ncontvars == 1 )
9936  {
9937  SCIP_VAR* var;
9938 
9939  assert(0 <= contvarpos && contvarpos < consdata->nvars);
9940  var = vars[contvarpos];
9941  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
9942 
9943  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9944  {
9945  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
9946  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9947  {
9948  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9949  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
9950  SCIPconsGetName(cons), SCIPvarGetName(var));
9951  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9952  if( infeasible )
9953  {
9954  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9955  *cutoff = TRUE;
9956 
9957  return SCIP_OKAY;
9958  }
9959  }
9960  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
9961  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9962  else if( !SCIPdoNotAggr(scip) )
9963  {
9964  SCIP_VAR* newvar;
9965  SCIP_Real absval;
9966  char newvarname[SCIP_MAXSTRLEN];
9967  SCIP_Bool redundant;
9968  SCIP_Bool aggregated;
9969 
9970  absval = REALABS(vals[contvarpos]);
9971 
9972  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
9973 
9974  /* create new implicit variable for aggregation */
9975  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
9977 
9978  /* add new variable to problem */
9979  SCIP_CALL( SCIPaddVar(scip, newvar) );
9980 
9981 #ifdef WITH_DEBUG_SOLUTION
9982  if( SCIPdebugIsMainscip(scip) )
9983  {
9984  SCIP_Real varval;
9985  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
9986  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
9987  }
9988 #endif
9989 
9990  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9991  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
9992  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
9993 
9994  /* aggregate continuous and implicit variable */
9995  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
9996 
9997  if( infeasible )
9998  {
9999  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10000  SCIPvarGetName(var), SCIPvarGetName(newvar));
10001  *cutoff = TRUE;
10002 
10003  /* release implicit variable */
10004  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10005 
10006  return SCIP_OKAY;
10007  }
10008 
10009  /* release implicit variable */
10010  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10011 
10012  if( aggregated )
10013  (*naggrvars)++;
10014  else
10015  return SCIP_OKAY;
10016  }
10017 
10018  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10019  * again
10020  */
10021  consdata->boundstightened = 0;
10022  consdata->rangedrowpropagated = 0;
10023  consdata->presolved = FALSE;
10024  }
10025  }
10026  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10027  {
10028  SCIP_VAR* var;
10029 
10030  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10031  * -> we don't convert integers into implints if the row is a 0/1-row
10032  */
10033  assert(varsintegral);
10034  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10035  var = vars[intvarpos];
10036  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10037 
10038  if( coefsintegral
10039  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10040  && SCIPisFeasIntegral(scip, consdata->rhs) )
10041  {
10042  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10043  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10044  SCIPconsGetName(cons), SCIPvarGetName(var));
10045  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10046  if( infeasible )
10047  {
10048  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10049  *cutoff = TRUE;
10050 
10051  return SCIP_OKAY;
10052  }
10053  }
10054  }
10055 
10056  return SCIP_OKAY;
10057 }
10058 
10059 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10060 static
10062  SCIP* scip, /**< SCIP data structure */
10063  SCIP_CONSDATA* consdata, /**< linear constraint data */
10064  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10065  * objective function */
10066  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10067  * this constraint */
10068  )
10069 {
10070  SCIP_VAR** vars;
10071  SCIP_VAR* var;
10072  SCIP_Real objval;
10073  SCIP_Bool negated;
10074  int nvars;
10075  int v;
10076 
10077  vars = consdata->vars;
10078  nvars = consdata->nvars;
10079 
10080  assert(vars != NULL);
10081 
10082  for( v = 0; v < nvars; ++v )
10083  {
10084  negated = FALSE;
10085  var = vars[v];
10086  assert(var != NULL);
10087 
10088  if( SCIPvarIsNegated(var) )
10089  {
10090  negated = TRUE;
10091  var = SCIPvarGetNegatedVar(var);
10092  assert(var != NULL);
10093  }
10094 
10095  objval = SCIPvarGetObj(var);
10096 
10097  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10098  * function
10099  */
10100  if( SCIPisZero(scip, objval) )
10101  return FALSE;
10102  else
10103  {
10104  SCIP_Real val;
10105 
10106  val = consdata->vals[v];
10107 
10108  if( negated )
10109  {
10110  if( v == 0 )
10111  {
10112  /* the first variable defines the scale */
10113  (*scale) = val / -objval;
10114 
10115  (*offset) += val;
10116  }
10117  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10118  (*offset) += val;
10119  else
10120  return FALSE;
10121  }
10122  else if( v == 0 )
10123  {
10124  /* the first variable defines the scale */
10125  (*scale) = val / objval;
10126  }
10127  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10128  return FALSE;
10129  }
10130  }
10131 
10132  return TRUE;
10133 }
10134 
10135 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10136  * objective coefficients and add an objective offset
10137  */
10138 static
10140  SCIP* scip, /**< SCIP data structure */
10141  SCIP_CONS* cons, /**< linear equation constraint */
10142  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10143  )
10144 {
10145  SCIP_CONSDATA* consdata;
10146  SCIP_Real offset;
10147  SCIP_Real scale;
10148  SCIP_Bool applicable;
10149  int nobjvars;
10150  int nvars;
10151  int v;
10152 
10153  assert(scip != NULL);
10154  assert(cons != NULL);
10155  assert(conshdlrdata != NULL);
10157  consdata = SCIPconsGetData(cons);
10158  assert(consdata != NULL);
10159  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10160 
10161  nvars = consdata->nvars;
10162  nobjvars = SCIPgetNObjVars(scip);
10163 
10164  /* check if the linear equality constraints does not have more variables than the objective function */
10165  if( nvars > nobjvars || nvars == 0 )
10166  return SCIP_OKAY;
10167 
10168  /* check for allowance of algorithm */
10169  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10170  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10171  return SCIP_OKAY;
10172 
10173  offset = consdata->rhs;
10174  scale = 1.0;
10175 
10176  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10177  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10178 
10179  if( applicable )
10180  {
10181  SCIP_VAR** vars;
10182 
10183  vars = consdata->vars;
10184  assert(vars != NULL);
10185 
10186  offset /= scale;
10187 
10188  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10189  SCIPconsGetName(cons), consdata->rhs, offset);
10190 
10191  /* set all objective coefficient to zero */
10192  for( v = 0; v < nvars; ++v )
10193  {
10194  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10195  }
10196 
10197  /* add an objective offset */
10198  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10199  }
10200 
10201  return SCIP_OKAY;
10202 }
10203 
10204 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10205 static
10207  SCIP* scip, /**< SCIP data structure */
10208  SCIP_CONS* cons, /**< constraint */
10209  SCIP_Real primalbound /**< feasible primal bound */
10210  )
10211 {
10212  SCIP_Real cutoffbound;
10213 
10214  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10215  * accepted
10216  */
10217  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10218 
10219  if( cutoffbound < SCIPgetCutoffbound(scip) )
10220  {
10221  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10222 
10223  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10224  }
10225  else
10226  {
10227  SCIP_CONSDATA* consdata;
10228 
10229  consdata = SCIPconsGetData(cons);
10230  assert(consdata != NULL);
10231 
10232  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10233  * resulted from one side
10234  */
10235  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10236  {
10237  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10238  * propagation
10239  */
10240  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10241  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10242  }
10243  }
10244 
10245  return SCIP_OKAY;
10246 }
10247 
10248 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10249  * constraint enters the LP by setting the initial and separated flag to FALSE
10250  */
10251 static
10253  SCIP* scip, /**< SCIP data structure */
10254  SCIP_CONS* cons, /**< linear constraint */
10255  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10256  )
10257 {
10258  SCIP_CONSDATA* consdata;
10259  SCIP_Real offset;
10260  SCIP_Real scale;
10261  SCIP_Bool applicable;
10262  int nobjvars;
10263  int nvars;
10264 
10265  assert(scip != NULL);
10266  assert(cons != NULL);
10267  assert(conshdlrdata != NULL);
10268 
10269  consdata = SCIPconsGetData(cons);
10270  assert(consdata != NULL);
10271 
10272  /* ignore equalities since these are covered by the method checkPartialObjective() */
10273  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10274  return SCIP_OKAY;
10275 
10276  nvars = consdata->nvars;
10277  nobjvars = SCIPgetNObjVars(scip);
10278 
10279  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10280  * initial and/or separated flag is set to FALSE
10281  */
10282  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10283  return SCIP_OKAY;
10284 
10285  offset = 0.0;
10286  scale = 1.0;
10287 
10288  /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10289  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10290  */
10291  if( nobjvars == 0 )
10292  return SCIP_OKAY;
10293 
10294  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10295  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10296 
10297  if( applicable )
10298  {
10299  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10300  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10301 
10302  if( SCIPisPositive(scip, scale) )
10303  {
10304  if( conshdlrdata->detectcutoffbound && rhsfinite )
10305  {
10306  SCIP_Real primalbound;
10307 
10308  primalbound = (consdata->rhs - offset) / scale;
10309 
10310  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10311  SCIPconsGetName(cons), primalbound);
10312 
10313  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10314  }
10315 
10316  if( conshdlrdata->detectlowerbound && lhsfinite )
10317  {
10318  SCIP_Real lowerbound;
10319 
10320  lowerbound = (consdata->lhs - offset) / scale;
10321 
10322  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10323  SCIPconsGetName(cons), lowerbound);
10324 
10325  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10326  }
10327 
10328  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10329  (conshdlrdata->detectlowerbound && !rhsfinite) )
10330  {
10331  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10332  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10333  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10334  }
10335  }
10336  else
10337  {
10338  if( conshdlrdata->detectlowerbound && rhsfinite )
10339  {
10340  SCIP_Real lowerbound;
10341 
10342  lowerbound = (consdata->rhs - offset) / scale;
10343 
10344  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10345  SCIPconsGetName(cons), lowerbound);
10346 
10347  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10348  }
10349 
10350  if( conshdlrdata->detectcutoffbound && lhsfinite )
10351  {
10352  SCIP_Real primalbound;
10353 
10354  primalbound = (consdata->lhs - offset) / scale;
10355 
10356  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10357  SCIPconsGetName(cons), primalbound);
10358 
10359  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10360  }
10361 
10362  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10363  (conshdlrdata->detectlowerbound && !lhsfinite) )
10364  {
10365  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10366  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10367  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10368  }
10369  }
10370  }
10371 
10372  return SCIP_OKAY;
10373 }
10374 
10375 /** converts special equalities */
10376 static
10378  SCIP* scip, /**< SCIP data structure */
10379  SCIP_CONS* cons, /**< linear constraint */
10380  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10381  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10382  int* nfixedvars, /**< pointer to count number of fixed variables */
10383  int* naggrvars, /**< pointer to count number of aggregated variables */
10384  int* ndelconss /**< pointer to count number of deleted constraints */
10385  )
10386 {
10387  SCIP_CONSDATA* consdata;
10388 
10389  assert(scip != NULL);
10390  assert(cons != NULL);
10391  assert(conshdlrdata != NULL);
10392  assert(cutoff != NULL);
10393  assert(nfixedvars != NULL);
10394  assert(naggrvars != NULL);
10395  assert(ndelconss != NULL);
10396 
10397  consdata = SCIPconsGetData(cons);
10398  assert(consdata != NULL);
10399  assert(consdata->removedfixings);
10400 
10401  /* do nothing on inequalities */
10402  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10403  return SCIP_OKAY;
10404 
10405  /* depending on the number of variables, call a special conversion method */
10406  if( consdata->nvars == 1 )
10407  {
10408  /* fix variable */
10409  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10410  }
10411  else if( consdata->nvars == 2 )
10412  {
10413  /* aggregate one of the variables */
10414  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10415  }
10416  else
10417  {
10418  /* check if the equality is part of the objective function */
10419  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10420 
10421  /* try to multi-aggregate one of the variables */
10422  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10423  }
10424 
10425  return SCIP_OKAY;
10426 }
10427 
10428 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10429  * integral
10430  */
10431 static
10433  SCIP* scip, /**< SCIP data structure */
10434  SCIP_CONSDATA* consdata, /**< linear constraint */
10435  int pos, /**< position of variable to be left out */
10436  SCIP_Real val /**< value to divide the coefficients by */
10437  )
10438 {
10439  int v;
10440 
10441  assert(scip != NULL);
10442  assert(consdata != NULL);
10443  assert(0 <= pos && pos < consdata->nvars);
10444 
10445  for( v = 0; v < consdata->nvars; ++v )
10446  {
10447  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10448  return FALSE;
10449  }
10450 
10451  return TRUE;
10452 }
10453 
10454 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10455  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10456  */
10457 static
10459  SCIP* scip, /**< SCIP data structure */
10460  SCIP_Real side, /**< lhs or rhs */
10461  SCIP_Real val, /**< coefficient */
10462  SCIP_Real minresactivity, /**< minimal residual activity */
10463  SCIP_Real maxresactivity, /**< maximal residual activity */
10464  SCIP_Real* minval, /**< pointer to store calculated minval */
10465  SCIP_Real* maxval /**< pointer to store calculated maxval */
10466  )
10467 {
10468  assert(scip != NULL);
10469  assert(minval != NULL);
10470  assert(maxval != NULL);
10471 
10472  if( val > 0.0 )
10473  {
10474  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10475  *minval = -maxresactivity;
10476  else
10477  *minval = (side - maxresactivity)/val;
10478 
10479  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10480  *maxval = -minresactivity;
10481  else
10482  *maxval = (side - minresactivity)/val;
10483  }
10484  else
10485  {
10486  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10487  *minval = minresactivity;
10488  else
10489  *minval = (side - minresactivity)/val;
10490 
10491  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10492  *maxval = maxresactivity;
10493  else
10494  *maxval = (side - maxresactivity)/val;
10495  }
10496 }
10497 
10498 
10499 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10500  * linear inequality
10501  */
10502 static
10504  SCIP* scip, /**< SCIP data structure */
10505  SCIP_CONS* cons, /**< linear constraint */
10506  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10507  int* nfixedvars, /**< pointer to count number of fixed variables */
10508  int* naggrvars, /**< pointer to count number of aggregated variables */
10509  int* ndelconss /**< pointer to count number of deleted constraints */
10510  )
10511 {
10512  SCIP_CONSDATA* consdata;
10513  SCIP_Bool lhsexists;
10514  SCIP_Bool rhsexists;
10515  SCIP_Bool bestisint;
10516  SCIP_Bool bestislhs;
10517  int bestpos;
10518  int i;
10519  int maxotherlocks;
10521  assert(scip != NULL);
10522  assert(cons != NULL);
10523  assert(cutoff != NULL);
10524  assert(nfixedvars != NULL);
10525  assert(naggrvars != NULL);
10526  assert(ndelconss != NULL);
10527 
10528  /* only process checked constraints (for which the locks are increased);
10529  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10530  * dualfix presolver
10531  */
10532  if( !SCIPconsIsChecked(cons) )
10533  return SCIP_OKAY;
10534 
10535  consdata = SCIPconsGetData(cons);
10536  assert(consdata != NULL);
10537 
10538  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10539  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10540 
10541  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10542  * can use it safely for aggregation and break the search loop
10543  */
10544  bestpos = -1;
10545  bestisint = TRUE;
10546  bestislhs = FALSE;
10547 
10548  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10549  * everything else would produce fill-in. Exceptions:
10550  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10551  * produced.
10552  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10553  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10554  * six nonzeros (two variables per substitution).
10555  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10556  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10557  * six nonzeros (three variables per substitution). God exists!
10558  */
10559  if( consdata->nvars <= 2 )
10560  maxotherlocks = INT_MAX;
10561  else if( consdata->nvars == 3 )
10562  maxotherlocks = 3;
10563  else if( consdata->nvars == 4 )
10564  maxotherlocks = 2;
10565  else
10566  maxotherlocks = 1;
10567 
10568  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10569  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10570  maxotherlocks++;
10571 
10572  for( i = 0; i < consdata->nvars && bestisint; ++i )
10573  {
10574  SCIP_VAR* var;
10575  SCIP_Bool isint;
10576  SCIP_Real val;
10577  SCIP_Real obj;
10578  SCIP_Real lb;
10579  SCIP_Real ub;
10580  SCIP_Bool agglhs;
10581  SCIP_Bool aggrhs;
10582 
10583  var = consdata->vars[i];
10585 
10586  /* if we already found a candidate, skip integers */
10587  if( bestpos >= 0 && isint )
10588  continue;
10589 
10590  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10591  * active, fixed, or single-aggregated with another binary variable
10592  */
10593  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10594  continue;
10595 
10596  if ( SCIPdoNotMultaggrVar(scip, var) )
10597  continue;
10598 
10599  val = consdata->vals[i];
10600  obj = SCIPvarGetObj(var);
10601  lb = SCIPvarGetLbGlobal(var);
10602  ub = SCIPvarGetUbGlobal(var);
10603 
10604  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10605  *
10606  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10607  * - constraint is the only one that forbids fixing the variable to its lower bound
10608  * - 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
10609  *
10610  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10611  * - constraint is the only one that forbids fixing the variable to its upper bound
10612  * - 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
10613  *
10614  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10615  * - constraint is the only one that forbids fixing the variable to its upper bound
10616  * - 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
10617  *
10618  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10619  * - constraint is the only one that forbids fixing the variable to its lower bound
10620  * - 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
10621  *
10622  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10623  * of all x_j
10624  * furthermore: we only want to apply this, if no fill-in will be produced
10625  */
10626  agglhs = lhsexists
10627  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10628  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10629  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10630  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10631  aggrhs = rhsexists
10632  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10633  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10634  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10635  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10636  if( agglhs || aggrhs )
10637  {
10638  SCIP_Real minresactivity;
10639  SCIP_Real maxresactivity;
10640  SCIP_Real minval;
10641  SCIP_Real maxval;
10642  SCIP_Bool minisrelax;
10643  SCIP_Bool maxisrelax;
10644  SCIP_Bool isminsettoinfinity;
10645  SCIP_Bool ismaxsettoinfinity;
10646 
10647  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10648  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10649  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10650  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10651 
10652  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10653  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10654  * This is needed, because we do not want to rely on relaxed finite resactivities.
10655  */
10656  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10657 
10658  if( agglhs )
10659  {
10660  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10661  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10662 
10663  assert(SCIPisLE(scip, minval, maxval));
10664  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10665  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10666  {
10667  SCIP_Real oldmaxresactivity;
10668  SCIP_Real oldminresactivity;
10669  SCIP_Bool recalculated;
10670 
10671  recalculated = FALSE;
10672  oldmaxresactivity = maxresactivity;
10673  oldminresactivity = minresactivity;
10674 
10675  /* check minresactivity for reliability */
10676  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10677  {
10678  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10679  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10680  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10681  }
10682 
10683  /* check maxresactivity for reliability */
10684  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10685  {
10686  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10687  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10688  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10689  }
10690 
10691  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10692  if( recalculated )
10693  {
10694  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10695 
10696  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10697  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10698 
10699  assert(SCIPisLE(scip, minval, maxval));
10700  }
10701 
10702  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10703  {
10704  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10705  * in the multi-aggregation
10706  */
10707  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10708  {
10709  bestpos = i;
10710  bestisint = isint;
10711  bestislhs = TRUE;
10712  continue; /* no need to also look at the right hand side */
10713  }
10714  }
10715  }
10716  }
10717 
10718  if( aggrhs )
10719  {
10720  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10721  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10722 
10723  assert(SCIPisLE(scip,minval,maxval));
10724  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10725  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10726  {
10727  SCIP_Real oldmaxresactivity;
10728  SCIP_Real oldminresactivity;
10729  SCIP_Bool recalculated;
10730 
10731  recalculated = FALSE;
10732  oldmaxresactivity = maxresactivity;
10733  oldminresactivity = minresactivity;
10734 
10735  /* check minresactivity for reliability */
10736  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10737  {
10738  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10739  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10740  }
10741 
10742  /* check maxresactivity for reliability */
10743  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10744  {
10745  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10746  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10747  }
10748 
10749  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10750  if( recalculated )
10751  {
10752  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10753  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10754  assert(SCIPisLE(scip,minval,maxval));
10755  }
10756 
10757  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10758  {
10759  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10760  * in the multi-aggregation
10761  */
10762  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10763  {
10764  bestpos = i;
10765  bestisint = isint;
10766  bestislhs = FALSE;
10767  }
10768  }
10769  }
10770  }
10771  }
10772  }
10773 
10774  if( bestpos >= 0 )
10775  {
10776  SCIP_VAR** aggrvars;
10777  SCIP_Real* aggrcoefs;
10778  SCIP_Real aggrconst;
10779  SCIP_VAR* bestvar;
10780  SCIP_Real bestval;
10781  SCIP_Real epsilon;
10782  int naggrs;
10783  int j;
10784  SCIP_Bool infeasible;
10785  SCIP_Bool aggregated;
10786  SCIP_Bool samevar;
10787  int supinf; /* counter for infinite contributions to the supremum of a possible
10788  * multi-aggregation
10789  */
10790  int infinf; /* counter for infinite contributions to the infimum of a possible
10791  * multi-aggregation
10792  */
10793 
10794  assert(!bestislhs || lhsexists);
10795  assert(bestislhs || rhsexists);
10796 
10797  bestvar = consdata->vars[bestpos];
10798  bestval = consdata->vals[bestpos];
10799  assert(bestisint ==
10801 
10802  /* allocate temporary memory */
10803  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10804  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10805 
10806  /* set up the multi-aggregation */
10807  SCIPdebugPrintCons(scip, cons, NULL);
10808  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10809  naggrs = 0;
10810  supinf = 0;
10811  infinf = 0;
10812  samevar = FALSE;
10813  epsilon = SCIPepsilon(scip);
10814 
10815  for( j = 0; j < consdata->nvars; ++j )
10816  {
10817  if( j != bestpos )
10818  {
10819  SCIP_Real absaggrcoef;
10820 
10821  aggrvars[naggrs] = consdata->vars[j];
10822  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10823  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10824 
10825  absaggrcoef = REALABS(aggrcoefs[naggrs]);
10826 
10827  /* do not try to multi aggregate, when numerical bad */
10828  if( absaggrcoef < epsilon )
10829  {
10830  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10831 
10832  /* free temporary memory */
10833  SCIPfreeBufferArray(scip, &aggrcoefs);
10834  SCIPfreeBufferArray(scip, &aggrvars);
10835 
10836  return SCIP_OKAY;
10837  }
10838 
10839  if( bestisint )
10840  {
10841  /* coefficient must be integral: round it to exact integral value */
10842  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10843  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10844  }
10845 
10846  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10847  {
10848  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10849  {
10850  ++supinf;
10851  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10852  {
10853  ++infinf;
10854  samevar = TRUE;
10855  }
10856  }
10857  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10858  ++infinf;
10859  }
10860  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10861  {
10862  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10863  {
10864  ++supinf;
10865  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10866  {
10867  ++infinf;
10868  samevar = TRUE;
10869  }
10870  }
10871  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10872  ++infinf;
10873  }
10874 
10875  naggrs++;
10876  }
10877  }
10878  assert(!samevar || (supinf > 0 && infinf > 0));
10879 
10880  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10881  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10882  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10883  assert(naggrs == consdata->nvars-1);
10884 
10885  /* right hand side must be integral: round it to exact integral value */
10886  if( bestisint )
10887  {
10888  assert(SCIPisIntegral(scip, aggrconst));
10889  aggrconst = SCIPfloor(scip, aggrconst+0.5);
10890  }
10891 
10892  aggregated = FALSE;
10893  infeasible = FALSE;
10894 
10895  /* perform the multi-aggregation */
10896  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
10897  {
10898  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
10899  * also convertLongEquality() early termination due to coefficients
10900  */
10901  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10902  }
10903  else
10904  {
10905  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10906  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10907  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10908  }
10909  /* free temporary memory */
10910  SCIPfreeBufferArray(scip, &aggrcoefs);
10911  SCIPfreeBufferArray(scip, &aggrvars);
10912 
10913  /* check for infeasible aggregation */
10914  if( infeasible )
10915  {
10916  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10917  *cutoff = TRUE;
10918  return SCIP_OKAY;
10919  }
10920 
10921  /* delete the constraint, if the aggregation was successful */
10922  if( aggregated )
10923  {
10924  SCIP_CALL( SCIPdelCons(scip, cons) );
10925 
10926  if( !consdata->upgraded )
10927  (*ndelconss)++;
10928  (*naggrvars)++;
10929  }
10930  else
10931  {
10932  SCIPdebugMsg(scip, "aggregation non successful!\n");
10933  }
10934  }
10935 
10936  return SCIP_OKAY;
10937 }
10938 
10939 #define BINWEIGHT 1
10940 #define INTWEIGHT 4
10941 #define CONTWEIGHT 8
10942 
10943 /** gets weight for variable in a "weighted number of variables" sum */
10944 static
10945 int getVarWeight(
10946  SCIP_VAR* var /**< variable to get weight for */
10947  )
10948 {
10949  switch( SCIPvarGetType(var) )
10950  {
10951  case SCIP_VARTYPE_BINARY:
10952  return BINWEIGHT;
10953  case SCIP_VARTYPE_INTEGER:
10954  case SCIP_VARTYPE_IMPLINT:
10955  return INTWEIGHT;
10957  return CONTWEIGHT;
10958  default:
10959  SCIPerrorMessage("invalid variable type\n");
10960  SCIPABORT();
10961  return 0; /*lint !e527*/
10962  }
10963 }
10964 
10965 /** tries to aggregate variables in equations a^Tx = lhs
10966  * in case there are at most two binary variables with an odd coefficient and all other
10967  * variables are not continuous and have an even coefficient then:
10968  * - exactly one odd binary variables
10969  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
10970  * - lhs is odd -> y = 1
10971  * - lhs is even -> y = 0
10972  * - exactly two odd binary variables
10973  * aggregate the two binary variables with odd coefficient
10974  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
10975  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
10976  */
10977 static
10979  SCIP* scip, /**< SCIP data structure */
10980  SCIP_CONS* cons, /**< linear constraint */
10981  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10982  int* nfixedvars, /**< pointer to count number of fixed variables */
10983  int* naggrvars, /**< pointer to count number of aggregated variables */
10984  int* ndelconss /**< pointer to count number of deleted constraints */
10985  )
10986 { /*lint --e{715}*/
10987  SCIP_CONSDATA* consdata;
10988  SCIP_Bool success;
10989 
10990  assert( scip != NULL );
10991  assert( cons != NULL );
10992 
10993  consdata = SCIPconsGetData(cons);
10994  assert( consdata != NULL );
10996  /* check if the linear constraint is an equation with integral right hand side */
10997  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
10998  return SCIP_OKAY;
10999 
11000  /* try to fix and aggregated variables until nothing is possible anymore */
11001  do
11002  {
11003  int v;
11004  int nvars;
11005  SCIP_VAR** vars;
11006  SCIP_Real* vals;
11007  SCIP_Real lhs;
11008  SCIP_Bool lhsodd;
11009 
11010  SCIP_Bool infeasible;
11011  SCIP_Bool fixed;
11012  SCIP_Bool aggregated;
11013  SCIP_Bool redundant;
11014 
11015  SCIP_VAR* var1;
11016  SCIP_VAR* var2;
11017  int noddvars;
11018 
11019  success = FALSE;
11020 
11021  lhs = consdata->lhs;
11022  vars = consdata->vars;
11023  vals = consdata->vals;
11024  nvars = consdata->nvars;
11025 
11026  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11027 
11028  var1 = NULL;
11029  var2 = NULL;
11030  noddvars = 0;
11031 
11032  /* search for binary variables with an odd coefficient */
11033  for( v = 0; v < nvars && noddvars < 3; ++v )
11034  {
11035  SCIP_Longint val;
11036 
11037  /* all coefficients and variables have to be integral */
11038  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11039  return SCIP_OKAY;
11040 
11041  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11042  if( val % 2 != 0 )
11043  {
11044  /* the odd values have to belong to binary variables */
11045  if( !SCIPvarIsBinary(vars[v]) )
11046  return SCIP_OKAY;
11047 
11048  if( noddvars == 0 )
11049  var1 = vars[v];
11050  else
11051  var2 = vars[v];
11052 
11053  noddvars++;
11054  }
11055  }
11056 
11057  /* check lhs is odd or even */
11058  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11059 
11060  if( noddvars == 1 )
11061  {
11062  assert( var1 != NULL );
11063 
11064  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11065  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11066 
11067  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11068 
11069  /* check for infeasibility of fixing */
11070  if( infeasible )
11071  {
11072  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11073  *cutoff = TRUE;
11074  return SCIP_OKAY;
11075  }
11076 
11077  if( fixed )
11078  {
11079  SCIPdebugMsg(scip, " -> feasible fixing\n");
11080  (*nfixedvars)++;
11081  success = TRUE;
11082  }
11083  }
11084  else if( noddvars == 2 )
11085  {
11086  assert( var1 != NULL );
11087  assert( var2 != NULL );
11088 
11089  /* aggregate the two variables with odd coefficient
11090  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11091  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11092  */
11093  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11094  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11095 
11096  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11097  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11098 
11099  /* check for infeasibility of aggregation */
11100  if( infeasible )
11101  {
11102  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11103  *cutoff = TRUE;
11104  return SCIP_OKAY;
11105  }
11106 
11107  /* count the aggregation */
11108  if( aggregated )
11109  {
11110  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11111  (*naggrvars)++;
11112  success = TRUE;
11113  }
11114  }
11115 
11116  if( success )
11117  {
11118  /* apply fixings and aggregation to successfully rerun this presolving step */
11119  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11120 
11121  if( infeasible )
11122  {
11123  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11124  *cutoff = TRUE;
11125  return SCIP_OKAY;
11126  }
11127 
11128  /* normalize constraint */
11129  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11130 
11131  if( infeasible )
11132  {
11133  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11134  *cutoff = TRUE;
11135  return SCIP_OKAY;
11136  }
11137  }
11138  }
11139  while( success );
11140 
11141  return SCIP_OKAY;
11142 }
11143 
11144 
11145 
11146 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11147  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11148  * coefficients
11149  */
11150 static
11151 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11152 { /*lint --e{715}*/
11153  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11154  SCIP_VARTYPE vartype1;
11155  SCIP_VARTYPE vartype2;
11156  SCIP_Real value;
11157 
11158  assert(consdata != NULL);
11159  assert(0 <= ind1 && ind1 < consdata->nvars);
11160  assert(0 <= ind2 && ind2 < consdata->nvars);
11161 
11162  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11163  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11164 
11165  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11166  {
11167  /* continuous varibles will be sorted to the back */
11168  if( vartype2 != vartype1 )
11169  return +1;
11170  /* both variables are continuous */
11171  else
11172  return 0;
11173  }
11174  /* continuous variables will be sorted to the back */
11175  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11176  return -1;
11177 
11178  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11179 
11180  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11181  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11182 }
11183 
11184 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11185  * common divisor
11186  *
11187  * 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
11188  * constraint to 1^Tx = 1
11189  */
11190 static
11192  SCIP* scip, /**< SCIP data structure */
11193  SCIP_CONS* cons, /**< linear constraint */
11194  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11195  int* nchgsides /**< pointer to store the amount of changed sides */
11196  )
11197 {
11198  SCIP_CONSDATA* consdata;
11199  SCIP_VAR** vars;
11200  SCIP_Real* vals;
11201  SCIP_Real minval;
11202  SCIP_Real secondminval;
11203  SCIP_Real maxval;
11204  SCIP_Real lhs;
11205  SCIP_Real rhs;
11206  int nvars;
11207  int v;
11209  /* we must not change a modifiable constraint in any way */
11210  if( SCIPconsIsModifiable(cons) )
11211  return SCIP_OKAY;
11212 
11213  if( SCIPconsIsDeleted(cons) )
11214  return SCIP_OKAY;
11215 
11216  consdata = SCIPconsGetData(cons);
11217  assert(consdata != NULL);
11218 
11219  nvars = consdata->nvars;
11220 
11221  /* do not check empty or bound-constraints */
11222  if( nvars < 2 )
11223  return SCIP_OKAY;
11224 
11225  vals = consdata->vals;
11226  vars = consdata->vars;
11227  assert(vars != NULL);
11228  assert(vals != NULL);
11229 
11230  lhs = consdata->lhs;
11231  rhs = consdata->rhs;
11232  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11233  assert(!SCIPisNegative(scip, rhs));
11234 
11235  minval = SCIP_INVALID;
11236  secondminval = SCIP_INVALID;
11237  maxval = -SCIP_INVALID;
11238 
11239  for( v = nvars - 1; v >= 0; --v )
11240  {
11241  if( SCIPvarIsBinary(vars[v]) )
11242  {
11243  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11244  {
11245  secondminval = minval;
11246  minval = vals[v];
11247  }
11248  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11249  secondminval = vals[v];
11250 
11251  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11252  maxval = vals[v];
11253  }
11254  else
11255  break;
11256  }
11257 
11258  /* check if all variables are binary */
11259  if( v == -1 )
11260  {
11261  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11262  return SCIP_OKAY;
11263 
11264  /* check if we can and need to choose exactly one binary variable */
11265  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11266  {
11267  /* change all coefficients to 1.0 */
11268  for( v = nvars - 1; v >= 0; --v )
11269  {
11270  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11271  }
11272  (*nchgcoefs) += nvars;
11273 
11274  /* replace old right and left hand side with 1.0 */
11275  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11276  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11277  (*nchgsides) += 2;
11278  }
11279  }
11280 
11281  return SCIP_OKAY;
11282 }
11283 
11284 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11285  * for equations @see rangedRowSimplify() will be called
11286  *
11287  * there are several different coefficient reduction steps which will be applied
11288  *
11289  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11290  *
11291  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11292  *
11293  * 2. We try to remove redundant fractional parts in a constraint
11294  *
11295  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11296  *
11297  * 3. We are using the greatest common divisor for further reductions
11298  *
11299  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11300  * integral
11301  */
11302 static
11304  SCIP* scip, /**< SCIP data structure */
11305  SCIP_CONS* cons, /**< linear constraint */
11306  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11307  int* nchgsides, /**< pointer to store the amount of changed sides */
11308  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11309  )
11310 {
11311  SCIP_CONSDATA* consdata;
11312  SCIP_VAR** vars;
11313  SCIP_Real* vals;
11314  int* perm;
11315  SCIP_Real minactsub;
11316  SCIP_Real maxactsub;
11317  SCIP_Real siderest;
11318  SCIP_Real feastol;
11319  SCIP_Real newcoef;
11320  SCIP_Real absval;
11321  SCIP_Real side;
11322  SCIP_Real lhs;
11323  SCIP_Real rhs;
11324  SCIP_Real lb;
11325  SCIP_Real ub;
11326  SCIP_Longint restcoef;
11327  SCIP_Longint oldgcd;
11328  SCIP_Longint rest;
11329  SCIP_Longint gcd;
11330  SCIP_Bool isminsettoinfinity;
11331  SCIP_Bool ismaxsettoinfinity;
11332  SCIP_Bool isminrelax;
11333  SCIP_Bool ismaxrelax;
11334  SCIP_Bool allcoefintegral;
11335  SCIP_Bool onlybin;
11336  SCIP_Bool hasrhs;
11337  SCIP_Bool haslhs;
11338  int oldnchgcoefs;
11339  int oldnchgsides;
11340  int foundbin;
11341  int candpos;
11342  int candpos2;
11343  int offsetv;
11344  int nvars;
11345  int v;
11346  int w;
11347 
11348  assert(scip != NULL);
11349  assert(cons != NULL);
11350  assert(nchgcoefs != NULL);
11351  assert(nchgsides != NULL);
11352 
11353  *infeasible = FALSE;
11354 
11355  /* we must not change a modifiable constraint in any way */
11356  if( SCIPconsIsModifiable(cons) )
11357  return SCIP_OKAY;
11358 
11359  if( SCIPconsIsDeleted(cons) )
11360  return SCIP_OKAY;
11361 
11362  consdata = SCIPconsGetData(cons);
11363  assert(consdata != NULL);
11364 
11365  nvars = consdata->nvars;
11366 
11367  /* do not check empty or bound-constraints */
11368  if( nvars <= 2 )
11369  return SCIP_OKAY;
11370 
11371  /* update maximal activity delta if necessary */
11372  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11373  consdataRecomputeMaxActivityDelta(scip, consdata);
11374 
11375  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11376  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11377  checkMaxActivityDelta(scip, consdata);
11378 
11379  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11380  * accordingly
11381  */
11382  /* can only work with valid non-infinity activities per variable */
11383  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11384  return SCIP_OKAY;
11385 
11386  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11387  * but the eventsystem seems to be full
11388  */
11389  consdata->normalized = FALSE;
11390 
11391  /* normalize constraint */
11392  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11393  assert(nvars == consdata->nvars);
11394 
11395  if( *infeasible )
11396  return SCIP_OKAY;
11397 
11398  if( !consdata->normalized )
11399  return SCIP_OKAY;
11400 
11401  lhs = consdata->lhs;
11402  rhs = consdata->rhs;
11403  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11404  assert(!SCIPisNegative(scip, rhs));
11405 
11406  if( !SCIPisInfinity(scip, -lhs) )
11407  haslhs = TRUE;
11408  else
11409  haslhs = FALSE;
11410 
11411  if( !SCIPisInfinity(scip, rhs) )
11412  hasrhs = TRUE;
11413  else
11414  hasrhs = FALSE;
11415 
11416  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11417  SCIPdebug( oldnchgsides = *nchgsides; )
11418 
11419  /* @todo also work on ranged rows */
11420  if( haslhs && hasrhs )
11421  {
11422  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11423 
11424  return SCIP_OKAY;
11425  }
11426  assert(haslhs != hasrhs);
11427 
11428  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11429  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11430  assert(!haslhs || !SCIPisNegative(scip, lhs));
11431 
11432  /* get temporary memory to store the sorted permutation */
11433  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11434 
11435  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11436  * value of their coefficients
11437  */
11438  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11439 
11440  /* perform sorting after permutation array */
11441  permSortConsdata(consdata, perm, nvars);
11442  consdata->sorted = FALSE;
11443  consdata->binvarssorted = FALSE;
11444 
11445  vars = consdata->vars;
11446  vals = consdata->vals;
11447  assert(vars != NULL);
11448  assert(vals != NULL);
11449  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11450 
11451  /* free temporary memory */
11452  SCIPfreeBufferArray(scip, &perm);
11453 
11454  /* only check constraints with at least two non continuous variables */
11455  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11456  return SCIP_OKAY;
11457 
11458  /* do not process constraints when all coefficients are 1.0 */
11459  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11460  return SCIP_OKAY;
11461 
11462  feastol = SCIPfeastol(scip);
11463 
11464  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11465  SCIPdebugPrintCons(scip, cons, NULL);
11466 
11467  /* get global activities */
11468  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11469  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11470 
11471  /* cannot work with infinite activities */
11472  if( isminsettoinfinity || ismaxsettoinfinity )
11473  return SCIP_OKAY;
11474 
11475  assert(!isminrelax);
11476  assert(!ismaxrelax);
11477  assert(maxactsub > minactsub);
11478  assert(!SCIPisInfinity(scip, -minactsub));
11479  assert(!SCIPisInfinity(scip, maxactsub));
11480 
11481  v = 0;
11482  offsetv = -1;
11483  side = haslhs ? lhs : rhs;
11484 
11485  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11486  * do not need to look at the large coefficients
11487  *
11488  * e.g. all x are binary, z are positive integer
11489  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11490  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11491  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11492  *
11493  * can be changed to
11494  *
11495  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11496  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11497  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11498  */
11499 
11500  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11501  * hand side, we cannot apply the extra reduction step and need to reset v
11502  *
11503  * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 for all i is not a solution, but if we would do a change on the
11504  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11505  * for all i is a solution
11506  *
11507  * also redundancy of variables would not be correctly determined in such a case
11508  */
11509  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11510  {
11511  v = 1;
11512 
11513  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11514  {
11515  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11516  * extra step, which might have worked
11517  */
11518  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11519  {
11520  v = 0;
11521  break;
11522  }
11523 
11524  ++v;
11525  }
11526 
11527  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11528  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11529  if( v == nvars )
11530  return SCIP_OKAY;
11531 
11532  /* cannot work with continuous variables which have a big coefficient */
11533  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11534  return SCIP_OKAY;
11535 
11536  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11537  if( SCIPisEQ(scip, side, -vals[v]) )
11538  v = 0;
11539 
11540  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11541  * reduction
11542  */
11543  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11544  v = 0;
11545 
11546  if( v > 0 )
11547  {
11548  assert(v < nvars);
11549 
11550  offsetv = v - 1;
11551 
11552  for( w = 0; w < v; ++w )
11553  {
11554  lb = SCIPvarGetLbGlobal(vars[w]);
11555  ub = SCIPvarGetUbGlobal(vars[w]);
11556 
11557  assert(vals[w] > 0);
11558 
11559  /* update residual activities */
11560  maxactsub -= ub * vals[w];
11561  minactsub -= lb * vals[w];
11562  assert(maxactsub > minactsub);
11563  }
11564  }
11565  }
11566 
11567  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11568  *
11569  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11570  *
11571  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11572  * to
11573  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11574  */
11575  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11576  {
11577  SCIP_Bool redundant = FALSE;
11578 
11579  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11580  assert(gcd >= 1);
11581 
11582  if( v == 0 )
11583  {
11584  lb = SCIPvarGetLbGlobal(vars[0]);
11585  ub = SCIPvarGetUbGlobal(vars[0]);
11586 
11587  /* update residual activities */
11588  if( vals[0] > 0 )
11589  {
11590  maxactsub -= ub * vals[0];
11591  minactsub -= lb * vals[0];
11592  }
11593  else
11594  {
11595  maxactsub -= lb * vals[0];
11596  minactsub -= ub * vals[0];
11597  }
11598  assert(maxactsub > minactsub);
11599  ++v;
11600  }
11601 
11602  siderest = -SCIP_INVALID;
11603  allcoefintegral = TRUE;
11604 
11605  /* check if some variables always fit into the given constraint */
11606  for( ; v < nvars - 1; ++v )
11607  {
11608  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11609  break;
11610 
11611  if( !SCIPisIntegral(scip, vals[v]) )
11612  {
11613  allcoefintegral = FALSE;
11614  break;
11615  }
11616 
11617  /* calculate greatest common divisor for all general and binary variables */
11618  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11619 
11620  if( gcd == 1 )
11621  break;
11622 
11623  lb = SCIPvarGetLbGlobal(vars[v]);
11624  ub = SCIPvarGetUbGlobal(vars[v]);
11625 
11626  assert(!SCIPisInfinity(scip, -lb));
11627  assert(!SCIPisInfinity(scip, ub));
11628 
11629  /* update residual activities */
11630  if( vals[v] > 0 )
11631  {
11632  maxactsub -= ub * vals[v];
11633  minactsub -= lb * vals[v];
11634  }
11635  else
11636  {
11637  maxactsub -= lb * vals[v];
11638  minactsub -= ub * vals[v];
11639  }
11640  assert(SCIPisGE(scip, maxactsub, minactsub));
11641 
11642  if( hasrhs )
11643  {
11644  /* determine the remainder of the right hand side and the gcd */
11645  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11646  }
11647  else
11648  {
11649  /* determine the remainder of the left hand side and the gcd */
11650  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11651  if( SCIPisZero(scip, siderest) )
11652  siderest = gcd;
11653  }
11654 
11655  /* early termination if the activities deceed the gcd */
11656  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11657  {
11658  redundant = TRUE;
11659  break;
11660  }
11661  }
11662  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11663 
11664  if( !redundant )
11665  {
11666  if( hasrhs )
11667  {
11668  /* determine the remainder of the right hand side and the gcd */
11669  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11670  }
11671  else
11672  {
11673  /* determine the remainder of the left hand side and the gcd */
11674  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11675  if( SCIPisZero(scip, siderest) )
11676  siderest = gcd;
11677  }
11678  }
11679  else
11680  ++v;
11681 
11682  SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n",
11683  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11684 
11685  /* check if we can remove redundant variables */
11686  if( v < nvars && (redundant ||
11687  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11688  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11689  {
11690  SCIP_Real oldcoef;
11691 
11692  /* double check the redundancy */
11693 #ifndef NDEBUG
11694  SCIP_Real tmpminactsub = 0.0;
11695  SCIP_Real tmpmaxactsub = 0.0;
11696 
11697  /* recompute residual activities */
11698  for( w = v; w < nvars; ++w )
11699  {
11700  lb = SCIPvarGetLbGlobal(vars[w]);
11701  ub = SCIPvarGetUbGlobal(vars[w]);
11702 
11703  assert(!SCIPisInfinity(scip, -lb));
11704  assert(!SCIPisInfinity(scip, ub));
11705 
11706  /* update residual activities */
11707  if( vals[w] > 0 )
11708  {
11709  tmpmaxactsub += ub * vals[w];
11710  tmpminactsub += lb * vals[w];
11711  }
11712  else
11713  {
11714  tmpmaxactsub += lb * vals[w];
11715  tmpminactsub += ub * vals[w];
11716  }
11717  assert(tmpmaxactsub >= tmpminactsub);
11718  }
11719 
11720  if( hasrhs )
11721  {
11722  assert(offsetv == -1);
11723 
11724  /* determine the remainder of the right hand side and the gcd */
11725  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11726  }
11727  else
11728  {
11729  /* determine the remainder of the left hand side and the gcd */
11730  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11731  if( SCIPisZero(scip, siderest) )
11732  siderest = gcd;
11733  }
11734 
11735  /* does the redundancy really is fulfilled */
11736  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11737 #endif
11738 
11739  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11740  nvars - v, SCIPconsGetName(cons));
11741 
11742  /* remove redundant variables */
11743  for( w = nvars - 1; w >= v; --w )
11744  {
11745  SCIP_CALL( delCoefPos(scip, cons, w) );
11746  }
11747  (*nchgcoefs) += (nvars - v);
11748 
11749  assert(w >= 0);
11750 
11751  oldcoef = vals[w];
11752 
11753  /* normalize constraint */
11754  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11755  assert(vars == consdata->vars);
11756  assert(vals == consdata->vals);
11757  assert(w < consdata->nvars);
11758 
11759  if( *infeasible )
11760  return SCIP_OKAY;
11761 
11762  /* compute new greatest common divisor due to normalization */
11763  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11764  assert(gcd >= 1);
11765 
11766  /* update side */
11767  if( hasrhs )
11768  {
11769  /* replace old with new right hand side */
11770  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11771  rhs = consdata->rhs;
11772  }
11773  else
11774  {
11775  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11776  {
11777  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11778  lhs = consdata->lhs;
11779  }
11780  else
11781  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11782  }
11783  ++(*nchgsides);
11784 
11785  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11786  assert(!haslhs || !SCIPisNegative(scip, lhs));
11787 
11788  /* get new constraint data */
11789  nvars = consdata->nvars;
11790  assert(nvars >= 2);
11791 
11792  allcoefintegral = TRUE;
11793 
11794 #ifndef NDEBUG
11795  /* check integrality */
11796  for( w = offsetv + 1; w < nvars; ++w )
11797  {
11798  assert(SCIPisIntegral(scip, vals[w]));
11799  }
11800 #endif
11801  SCIPdebugPrintCons(scip, cons, NULL);
11802  }
11803 
11804  /* try to find a better gcd, when having large coefficients */
11805  if( offsetv >= 0 && gcd == 1 )
11806  {
11807  /* calculate greatest common divisor for all general variables */
11808  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11809 
11810  if( gcd > 1 )
11811  {
11812  gcd = -1;
11813  candpos = -1;
11814 
11815  for( v = nvars - 1; v > offsetv; --v )
11816  {
11817  assert(!SCIPisZero(scip, vals[v]));
11818  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11819  break;
11820 
11821  if( !SCIPisIntegral(scip, vals[v]) )
11822  {
11823  allcoefintegral = FALSE;
11824  break;
11825  }
11826 
11827  oldgcd = gcd;
11828 
11829  if( gcd == -1 )
11830  {
11831  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11832  assert(gcd >= 1);
11833  }
11834  else
11835  {
11836  /* calculate greatest common divisor for all general and binary variables */
11837  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11838  }
11839 
11840  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11841  * can stop searching
11842  */
11843  if( gcd == 1 )
11844  {
11845  if( !SCIPvarIsBinary(vars[v]) )
11846  break;
11847 
11848  /* found candidate */
11849  if( candpos == -1 )
11850  {
11851  gcd = oldgcd;
11852  candpos = v;
11853  }
11854  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11855  else
11856  break;
11857  }
11858  }
11859  assert(v > offsetv || candpos > offsetv);
11860  }
11861  else
11862  candpos = -1;
11863  }
11864  else
11865  candpos = nvars - 1;
11866 
11867  /* check last coefficient for integrality */
11868  if( gcd > 1 && allcoefintegral && !redundant )
11869  {
11870  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11871  allcoefintegral = FALSE;
11872  }
11873 
11874  /* check for further necessary coefficient adjustments */
11875  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11876  {
11877  assert(offsetv + 1 < nvars);
11878  assert(0 <= candpos && candpos < nvars);
11879 
11880  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
11881  {
11882  SCIP_Bool notchangable = FALSE;
11883 
11884 #ifndef NDEBUG
11885  /* check integrality */
11886  for( w = offsetv + 1; w < nvars; ++w )
11887  {
11888  assert(SCIPisIntegral(scip, vals[w]));
11889  }
11890 #endif
11891 
11892  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11893  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11894  {
11895  /* determine the remainder of the side and the gcd */
11896  if( hasrhs )
11897  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11898  else
11899  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11900  assert(rest >= 0);
11901  assert(rest < gcd);
11902 
11903  /* determine the remainder of the coefficient candidate and the gcd */
11904  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11905  assert(restcoef >= 1);
11906  assert(restcoef < gcd);
11907 
11908  if( hasrhs )
11909  {
11910  /* calculate new coefficient */
11911  if( restcoef > rest )
11912  newcoef = vals[candpos] - restcoef + gcd;
11913  else
11914  newcoef = vals[candpos] - restcoef;
11915  }
11916  else
11917  {
11918  /* calculate new coefficient */
11919  if( rest == 0 || restcoef < rest )
11920  newcoef = vals[candpos] - restcoef;
11921  else
11922  newcoef = vals[candpos] - restcoef + gcd;
11923  }
11924 
11925  /* done */
11926 
11927  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11928  * another with the big coefficient was set to 1
11929  */
11930  if( hasrhs && SCIPisZero(scip, newcoef) )
11931  {
11932  notchangable = TRUE;
11933  }
11934  else if( SCIPisZero(scip, newcoef) )
11935  {
11936  /* delete old redundant coefficient */
11937  SCIP_CALL( delCoefPos(scip, cons, candpos) );
11938  ++(*nchgcoefs);
11939  }
11940  else
11941  {
11942  /* replace old with new coefficient */
11943  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11944  ++(*nchgcoefs);
11945  }
11946  }
11947  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11948  {
11949  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11950  }
11951 
11952  /* correct side and big coefficients */
11953  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11954  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11955  {
11956  if( haslhs )
11957  {
11958  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11959 
11960  SCIP_CALL( chgLhs(scip, cons, newcoef) );
11961  ++(*nchgsides);
11962  }
11963  else
11964  {
11965  assert(hasrhs);
11966  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
11967 
11968  SCIP_CALL( chgRhs(scip, cons, newcoef) );
11969  ++(*nchgsides);
11970  }
11971 
11972  /* correct coefficients up front */
11973  for( w = offsetv; w >= 0; --w )
11974  {
11975  assert(vals[w] > 0);
11976 
11977  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
11978  }
11979  (*nchgcoefs) += (offsetv + 1);
11980  }
11981 
11982  if( !notchangable )
11983  {
11984  /* normalize constraint */
11985  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11986  assert(vars == consdata->vars);
11987  assert(vals == consdata->vals);
11988 
11989  if( *infeasible )
11990  return SCIP_OKAY;
11991 
11992  /* get new constraint data */
11993  nvars = consdata->nvars;
11994  assert(nvars >= 2);
11995 
11996  SCIPdebugPrintCons(scip, cons, NULL);
11997 
11998  lhs = consdata->lhs;
11999  rhs = consdata->rhs;
12000  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12001  assert(!haslhs || !SCIPisNegative(scip, lhs));
12002  }
12003  }
12004  }
12005  }
12006 
12007  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12008  /* no continuous variables are left over */
12009  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12010  return SCIP_OKAY;
12011 
12012  onlybin = TRUE;
12013  allcoefintegral = TRUE;
12014  /* check if all variables are of binary type */
12015  for( v = nvars - 1; v >= 0; --v )
12016  {
12017  if( !SCIPvarIsBinary(vars[v]) )
12018  onlybin = FALSE;
12019  if( !SCIPisIntegral(scip, vals[v]) )
12020  allcoefintegral = FALSE;
12021  }
12022 
12023  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12024  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12025  *
12026  * @todo there are some steps missing ....
12027  */
12028  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12029  {
12030  SCIP_Real val;
12031  SCIP_Real newval;
12032  SCIP_Real frac = 0.0;
12033  SCIP_Bool found = FALSE;
12034 
12035  if( hasrhs )
12036  {
12037  if( allcoefintegral )
12038  {
12039  /* replace old with new right hand side */
12040  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12041  ++(*nchgsides);
12042  }
12043  else
12044  {
12045  siderest = rhs - SCIPfloor(scip, rhs);
12046 
12047  /* try to round down all non-integral coefficients */
12048  for( v = nvars - 1; v >= 0; --v )
12049  {
12050  val = vals[v];
12051 
12052  /* add up all possible fractional parts */
12053  if( !SCIPisIntegral(scip, val) )
12054  {
12055  lb = SCIPvarGetLbGlobal(vars[v]);
12056  ub = SCIPvarGetUbGlobal(vars[v]);
12057 
12058  /* at least one bound need to be at zero */
12059  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12060  return SCIP_OKAY;
12061 
12062  /* swap bounds for 'standard' form */
12063  if( !SCIPisFeasZero(scip, lb) )
12064  {
12065  ub = lb;
12066  val *= -1;
12067  }
12068 
12069  found = TRUE;
12070 
12071  frac += (val - SCIPfloor(scip, val)) * ub;
12072 
12073  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12074  *
12075  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12076  * x3, x4 set to 1 would be infeasible but feasible after flooring
12077  */
12078  if( SCIPisGT(scip, frac, siderest) )
12079  return SCIP_OKAY;
12080  }
12081  }
12082  assert(v == -1);
12083 
12084  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12085 
12086  /* round rhs and coefficients to integral values */
12087  if( found )
12088  {
12089  for( v = nvars - 1; v >= 0; --v )
12090  {
12091  val = vals[v];
12092 
12093  /* add the whole fractional part */
12094  if( !SCIPisIntegral(scip, val) )
12095  {
12096  lb = SCIPvarGetLbGlobal(vars[v]);
12097 
12098  if( SCIPisFeasZero(scip, lb) )
12099  newval = SCIPfloor(scip, val);
12100  else
12101  newval = SCIPceil(scip, val);
12102 
12103  if( SCIPisZero(scip, newval) )
12104  {
12105  /* delete old redundant coefficient */
12106  SCIP_CALL( delCoefPos(scip, cons, v) );
12107  ++(*nchgcoefs);
12108  }
12109  else
12110  {
12111  /* replace old with new coefficient */
12112  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12113  ++(*nchgcoefs);
12114  }
12115  }
12116  }
12117  }
12118 
12119  /* replace old with new right hand side */
12120  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12121  ++(*nchgsides);
12122  }
12123  }
12124  else
12125  {
12126  if( allcoefintegral )
12127  {
12128  /* replace old with new left hand side */
12129  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12130  ++(*nchgsides);
12131  }
12132  else
12133  {
12134  /* cannot floor left hand side to zero */
12135  if( SCIPisLT(scip, lhs, 1.0) )
12136  return SCIP_OKAY;
12137 
12138  siderest = lhs - SCIPfloor(scip, lhs);
12139 
12140  /* try to round down all non-integral coefficients */
12141  for( v = nvars - 1; v >= 0; --v )
12142  {
12143  val = vals[v];
12144 
12145  /* add up all possible fractional parts */
12146  if( !SCIPisIntegral(scip, val) )
12147  {
12148  lb = SCIPvarGetLbGlobal(vars[v]);
12149  ub = SCIPvarGetUbGlobal(vars[v]);
12150 
12151  /* at least one bound need to be at zero */
12152  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12153  return SCIP_OKAY;
12154 
12155  /* swap bounds for 'standard' form */
12156  if( !SCIPisFeasZero(scip, lb) )
12157  {
12158  ub = lb;
12159  val *= -1;
12160  }
12161 
12162  /* cannot floor to zero */
12163  if( SCIPisLT(scip, val, 1.0) )
12164  return SCIP_OKAY;
12165 
12166  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12167  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12168  return SCIP_OKAY;
12169 
12170  found = TRUE;
12171 
12172  frac += (val - SCIPfloor(scip, val)) * ub;
12173 
12174  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12175  * fractional parts of the variables, we cannot tighten the coefficients
12176  *
12177  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12178  * x2-x4 set to 1 would be feasible but not after flooring
12179  */
12180  if( SCIPisGE(scip, frac, 1 + siderest) )
12181  return SCIP_OKAY;
12182  }
12183  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12184  else
12185  return SCIP_OKAY;
12186  }
12187  assert(v == -1);
12188 
12189  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12190 
12191  /* round lhs and coefficients to integral values */
12192  if( found )
12193  {
12194  for( v = nvars - 1; v >= 0; --v )
12195  {
12196  val = vals[v];
12197 
12198  /* add the whole fractional part */
12199  if( !SCIPisIntegral(scip, val) )
12200  {
12201  lb = SCIPvarGetLbGlobal(vars[v]);
12202 
12203  if( SCIPisFeasZero(scip, lb) )
12204  newval = SCIPfloor(scip, val);
12205  else
12206  newval = SCIPceil(scip, val);
12207 
12208  if( SCIPisZero(scip, newval) )
12209  {
12210  /* delete old redundant coefficient */
12211  SCIP_CALL( delCoefPos(scip, cons, v) );
12212  ++(*nchgcoefs);
12213  }
12214  else
12215  {
12216  /* replace old with new coefficient */
12217  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12218  ++(*nchgcoefs);
12219  }
12220  }
12221  }
12222  }
12223 
12224  /* replace old with new left hand side */
12225  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12226  ++(*nchgsides);
12227  }
12228  }
12229 
12230  /* normalize constraint */
12231  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12232  assert(vars == consdata->vars);
12233  assert(vals == consdata->vals);
12234 
12235  if( *infeasible )
12236  return SCIP_OKAY;
12237 
12238  rhs = consdata->rhs;
12239  lhs = consdata->lhs;
12240 
12241  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12242  assert(!haslhs || !SCIPisNegative(scip, lhs));
12243 
12244  SCIPdebugPrintCons(scip, cons, NULL);
12245 
12246  nvars = consdata->nvars;
12247  if( nvars < 2 )
12248  return SCIP_OKAY;
12249 
12250  allcoefintegral = TRUE;
12251 #ifndef NDEBUG
12252  /* debug check if all coefficients are really integral */
12253  for( v = nvars - 1; v >= 0; --v )
12254  assert(SCIPisIntegral(scip, vals[v]));
12255 #endif
12256  }
12257 
12258  /* @todo following can also work on non integral coefficients, need more investigation */
12259  /* only check constraints with integral coefficients on all integral variables */
12260  if( !allcoefintegral )
12261  return SCIP_OKAY;
12262 
12263  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12264  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12265  return SCIP_OKAY;
12266 
12267  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12268  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12269  return SCIP_OKAY;
12270 
12271  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12272  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12273  return SCIP_OKAY;
12274 
12275  assert(nvars >= 2);
12276 
12277  /* start gcd procedure for all variables */
12278  do
12279  {
12280  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12281  SCIPdebug( oldnchgsides = *nchgsides; )
12282 
12283  /* stop if we have two coeffcients which are one in absolute value */
12284  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12285  return SCIP_OKAY;
12286 
12287  gcd = -1;
12288 
12289  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12290  * because coefficients of non-binary variables might have changed to zero */
12291  if( !onlybin )
12292  {
12293  foundbin = -1;
12294  onlybin = TRUE;
12295 
12296  for( v = nvars - 1; v >= 0; --v )
12297  {
12298  assert(!SCIPisZero(scip, vals[v]));
12299  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12300 
12301  if( SCIPvarIsBinary(vars[v]) )
12302  {
12303  if( foundbin == -1 )
12304  foundbin = v;
12305  continue;
12306  }
12307  else
12308  onlybin = FALSE;
12309 
12310  absval = REALABS(vals[v]);
12311  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12312  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12313  */
12314  assert(SCIPisFeasIntegral(scip, absval));
12315 
12316  if( gcd == -1 )
12317  {
12318  gcd = (SCIP_Longint)(absval + feastol);
12319  assert(gcd >= 1);
12320  }
12321  else
12322  {
12323  /* calculate greatest common divisor for all general variables */
12324  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12325  }
12326  if( gcd == 1 )
12327  break;
12328  }
12329  }
12330  else
12331  foundbin = nvars - 1;
12332 
12333  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12334  if( gcd == 1 || foundbin == -1)
12335  return SCIP_OKAY;
12336 
12337  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12338 
12339  candpos = -1;
12340  candpos2 = -1;
12341 
12342  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12343  * change the coefficient
12344  */
12345  for( v = foundbin; v >= 0; --v )
12346  {
12347  if( onlybin || SCIPvarIsBinary(vars[v]) )
12348  {
12349  absval = REALABS(vals[v]);
12350  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12351  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12352  */
12353  assert(SCIPisFeasIntegral(scip, absval));
12354 
12355  oldgcd = gcd;
12356 
12357  if( gcd == -1 )
12358  {
12359  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12360  assert(gcd >= 1);
12361  }
12362  else
12363  {
12364  /* calculate greatest common divisor for all general and binary variables */
12365  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12366  }
12367 
12368  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12369  * can terminate
12370  */
12371  if( gcd == 1 )
12372  {
12373  /* found candidate */
12374  if( candpos == -1 )
12375  {
12376  gcd = oldgcd;
12377  candpos = v;
12378 
12379  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12380  * the coefficient change
12381  */
12382  if( onlybin && v == foundbin - 1 )
12383  candpos2 = foundbin;
12384  }
12385  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12386  else
12387  {
12388  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12389  {
12390  assert(candpos2 == nvars - 1);
12391 
12392  /* take new candidates */
12393  candpos = candpos2;
12394 
12395  /* recalculate gcd from scratch */
12396  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12397  assert(gcd >= 1);
12398 
12399  /* calculate greatest common divisor for all general and binary variables */
12400  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12401  if( gcd == 1 )
12402  return SCIP_OKAY;
12403  }
12404  else
12405  /* cannot determine a possible coefficient for reduction */
12406  return SCIP_OKAY;
12407  }
12408  }
12409  }
12410  }
12411  assert(gcd >= 2);
12412 
12413  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12414  * further
12415  */
12416  assert(candpos >= 0 && candpos < nvars);
12417 
12418  /* all variables and all coefficients are integral, so the side should be too */
12419  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12420 
12421  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12422  * @see normalizeCons()
12423  */
12424  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12425  assert(!haslhs || !SCIPisNegative(scip, lhs));
12426 
12427  /* determine the remainder of the side and the gcd */
12428  if( hasrhs )
12429  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12430  else
12431  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12432  assert(rest >= 0);
12433  assert(rest < gcd);
12434 
12435  /* determine the remainder of the coefficient candidate and the gcd */
12436  if( vals[candpos] < 0 )
12437  {
12438  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12439  assert(restcoef <= -1);
12440  restcoef += gcd;
12441  }
12442  else
12443  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12444  assert(restcoef >= 1);
12445  assert(restcoef < gcd);
12446 
12447  if( hasrhs )
12448  {
12449  if( rest > 0 )
12450  {
12451  /* replace old with new right hand side */
12452  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12453  ++(*nchgsides);
12454  }
12455 
12456  /* calculate new coefficient */
12457  if( restcoef > rest )
12458  newcoef = vals[candpos] - restcoef + gcd;
12459  else
12460  newcoef = vals[candpos] - restcoef;
12461  }
12462  else
12463  {
12464  if( rest > 0 )
12465  {
12466  /* replace old with new left hand side */
12467  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12468  ++(*nchgsides);
12469  }
12470 
12471  /* calculate new coefficient */
12472  if( rest == 0 || restcoef < rest )
12473  newcoef = vals[candpos] - restcoef;
12474  else
12475  newcoef = vals[candpos] - restcoef + gcd;
12476  }
12477  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12478 
12479  SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12480 
12481  if( SCIPisZero(scip, newcoef) )
12482  {
12483  /* delete redundant coefficient */
12484  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12485  }
12486  else
12487  {
12488  /* replace old with new coefficient */
12489  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12490  }
12491  ++(*nchgcoefs);
12492 
12493  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12494  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12495  assert(vars == consdata->vars);
12496  assert(vals == consdata->vals);
12497 
12498  if( *infeasible )
12499  return SCIP_OKAY;
12500 
12501  SCIPdebugPrintCons(scip, cons, NULL);
12502 
12503  rhs = consdata->rhs;
12504  lhs = consdata->lhs;
12505  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12506  assert(!haslhs || !SCIPisNegative(scip, lhs));
12507 
12508  nvars = consdata->nvars;
12509 
12510  SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12511  }
12512  while( nvars >= 2 );
12513 
12514  return SCIP_OKAY;
12515 }
12516 
12517 
12518 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12519  * cons0 := a * cons0 + b * cons1,
12520  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12521  * for numerical stability, we will only accept integral a and b;
12522  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12523  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12524  */
12525 static
12527  SCIP* scip, /**< SCIP data structure */
12528  SCIP_CONS* cons0, /**< (in)equality to modify */
12529  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12530  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12531  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12532  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12533  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12534  int nvarscommon, /**< number of variables, that appear in both constraints */
12535  int commonidxweight, /**< variable weight sum of common variables */
12536  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12537  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12538  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12539  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12540  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12541  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12542  )
12544  SCIP_CONSDATA* consdata0;
12545  SCIP_CONSDATA* consdata1;
12546  SCIP_Real a;
12547  SCIP_Real b;
12548  SCIP_Real aggrcoef;
12549  SCIP_Real scalarsum;
12550  SCIP_Real bestscalarsum;
12551  SCIP_Bool betterscalarsum;
12552  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12553  int varweight;
12554  int nvars;
12555  int bestvarweight;
12556  int bestnvars;
12557  int bestv;
12558  int v;
12559  int i;
12560 
12561  assert(scip != NULL);
12562  assert(cons0 != NULL);
12563  assert(cons1 != NULL);
12564  assert(commonidx0 != NULL);
12565  assert(commonidx1 != NULL);
12566  assert(diffidx0minus1 != NULL);
12567  assert(diffidx1minus0 != NULL);
12568  assert(nvarscommon >= 1);
12569  assert(commonidxweight >= nvarscommon);
12570  assert(nchgcoefs != NULL);
12571  assert(aggregated != NULL);
12572 
12573  assert(SCIPconsIsActive(cons0));
12574  assert(SCIPconsIsActive(cons1));
12575 
12576  *infeasible = FALSE;
12577 
12578  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12579 
12580  /* cons0 is an (in)equality */
12581  consdata0 = SCIPconsGetData(cons0);
12582  assert(consdata0 != NULL);
12583  assert(consdata0->nvars >= 1);
12584  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12585  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12586 
12587  /* cons1 is an equality */
12588  consdata1 = SCIPconsGetData(cons1);
12589  assert(consdata1 != NULL);
12590  assert(consdata1->nvars >= 1);
12591  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12592  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12593 
12594  *aggregated = FALSE;
12595 
12596  /* search for the best common variable such that
12597  * val1[var] * consdata0 - val0[var] * consdata1
12598  * has least weighted number of variables
12599  */
12600  bestvarweight = commonidxweight + diffidx0minus1weight;
12601  bestnvars = consdata0->nvars;
12602  bestv = -1;
12603  bestscalarsum = 0.0;
12604  commonvarlindependent = TRUE;
12605  for( v = 0; v < nvarscommon; ++v )
12606  {
12607  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12608  a = consdata1->vals[commonidx1[v]];
12609  b = -consdata0->vals[commonidx0[v]];
12610 
12611  /* only try aggregation, if coefficients are integral (numerical stability) */
12612  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12613  {
12614  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12615  varweight = diffidx0minus1weight + diffidx1minus0weight;
12616  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12617  scalarsum = REALABS(a) + REALABS(b);
12618  betterscalarsum = (scalarsum < bestscalarsum);
12619  for( i = 0; i < nvarscommon
12620  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12621  {
12622  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12623  if( !SCIPisZero(scip, aggrcoef) )
12624  {
12625  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12626  nvars++;
12627  }
12628  }
12629  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12630  {
12631  bestv = v;
12632  bestvarweight = varweight;
12633  bestnvars = nvars;
12634  bestscalarsum = scalarsum;
12635  }
12636  }
12637 
12638  /* update commonvarlindependent flag, if still TRUE:
12639  * 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
12640  */
12641  if( commonvarlindependent && v > 0 )
12642  commonvarlindependent = SCIPisEQ(scip,
12643  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12644  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12645  }
12646 
12647  /* if better aggregation was found, create new constraint and delete old one */
12648  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12649  {
12650  SCIP_CONS* newcons;
12651  SCIP_CONSDATA* newconsdata;
12652  SCIP_VAR** newvars;
12653  SCIP_Real* newvals;
12654  SCIP_Real newlhs;
12655  SCIP_Real newrhs;
12656  int newnvars;
12657 
12658  if( bestv != -1 )
12659  {
12660  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12661  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12662  {
12663  a = consdata1->vals[commonidx1[bestv]];
12664  b = -consdata0->vals[commonidx0[bestv]];
12665  }
12666  else
12667  {
12668  a = -consdata1->vals[commonidx1[bestv]];
12669  b = consdata0->vals[commonidx0[bestv]];
12670  }
12671  assert(SCIPisIntegral(scip, a));
12672  assert(SCIPisPositive(scip, a));
12673  assert(SCIPisIntegral(scip, b));
12674  assert(!SCIPisZero(scip, b));
12675  }
12676  else
12677  {
12678  assert(commonvarlindependent);
12679  if( consdata1->vals[commonidx1[0]] > 0.0 )
12680  {
12681  a = consdata1->vals[commonidx1[0]];
12682  b = -consdata0->vals[commonidx0[0]];
12683  }
12684  else
12685  {
12686  a = -consdata1->vals[commonidx1[0]];
12687  b = consdata0->vals[commonidx0[0]];
12688  }
12689  assert(SCIPisPositive(scip, a));
12690  assert(!SCIPisZero(scip, b));
12691 
12692  /* if a/b is integral, then we can easily choose integer multipliers */
12693  if( SCIPisIntegral(scip, a/b) )
12694  {
12695  if( a/b > 0 )
12696  {
12697  a /= b;
12698  b = 1.0;
12699  }
12700  else
12701  {
12702  a /= -b;
12703  b = -1.0;
12704  }
12705  }
12706 
12707  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12708  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12709  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12710  }
12711 
12712  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12713  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12714  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12715  SCIPdebugPrintCons(scip, cons0, NULL);
12716  SCIPdebugPrintCons(scip, cons1, NULL);
12717 
12718  /* get temporary memory for creating the new linear constraint */
12719  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12720  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12721 
12722  /* calculate the common coefficients, if we have not recognized linear dependency */
12723  newnvars = 0;
12724  if( !commonvarlindependent )
12725  {
12726  for( i = 0; i < nvarscommon; ++i )
12727  {
12728  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12729  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12730 
12731  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12732  if( !SCIPisZero(scip, aggrcoef) )
12733  {
12734  assert(newnvars < bestnvars);
12735  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12736  newvals[newnvars] = aggrcoef;
12737  newnvars++;
12738  }
12739  }
12740  }
12741  else
12742  {
12743  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12744 #ifndef NDEBUG
12745  for( i = 0; i < nvarscommon; ++i )
12746  {
12747  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12748  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12749 
12750  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12751  assert(SCIPisZero(scip, aggrcoef));
12752  }
12753 #endif
12754  }
12755 
12756  /* calculate the coefficients appearing in cons0 but not in cons1 */
12757  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12758  {
12759  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12760 
12761  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12762  assert(!SCIPisZero(scip, aggrcoef));
12763  assert(newnvars < bestnvars);
12764  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12765  newvals[newnvars] = aggrcoef;
12766  newnvars++;
12767  }
12768 
12769  /* calculate the coefficients appearing in cons1 but not in cons0 */
12770  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12771  {
12772  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12773 
12774  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12775  assert(!SCIPisZero(scip, aggrcoef));
12776  assert(newnvars < bestnvars);
12777  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12778  newvals[newnvars] = aggrcoef;
12779  newnvars++;
12780  }
12781  assert(newnvars == bestnvars);
12782 
12783  /* calculate the new left and right hand side of the (in)equality */
12784  assert(!SCIPisInfinity(scip, -consdata1->lhs));
12785  assert(!SCIPisInfinity(scip, consdata1->rhs));
12786  if( SCIPisInfinity(scip, -consdata0->lhs) )
12787  newlhs = -SCIPinfinity(scip);
12788  else
12789  newlhs = a * consdata0->lhs + b * consdata1->lhs;
12790  if( SCIPisInfinity(scip, consdata0->rhs) )
12791  newrhs = SCIPinfinity(scip);
12792  else
12793  newrhs = a * consdata0->rhs + b * consdata1->rhs;
12794 
12795  /* create the new linear constraint */
12796  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12798  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12799  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12801 
12802  newconsdata = SCIPconsGetData(newcons);
12803  assert(newconsdata != NULL);
12804 
12805  /* copy the upgraded flag from the old cons0 to the new constraint */
12806  newconsdata->upgraded = consdata0->upgraded;
12807 
12808  /* normalize the new constraint */
12809  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12810 
12811  if( *infeasible )
12812  goto TERMINATE;
12813 
12814  /* check, if we really want to use the new constraint instead of the old one:
12815  * use the new one, if the maximum norm doesn't grow too much
12816  */
12817  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12818  {
12819  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12820  SCIPdebugPrintCons(scip, newcons, NULL);
12821 
12822  /* update the statistics: we changed all coefficients */
12823  if( !consdata0->upgraded )
12824  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12825  *aggregated = TRUE;
12826 
12827  /* delete the old constraint, and add the new linear constraint to the problem */
12828  SCIP_CALL( SCIPdelCons(scip, cons0) );
12829  SCIP_CALL( SCIPaddCons(scip, newcons) );
12830  }
12831 
12832  TERMINATE:
12833  /* release the new constraint */
12834  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12835 
12836  /* free temporary memory */
12837  SCIPfreeBufferArray(scip, &newvals);
12838  SCIPfreeBufferArray(scip, &newvars);
12839  }
12840 
12841  return SCIP_OKAY;
12842 }
12843 
12844 /** gets the key of the given element */
12845 static
12846 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12847 { /*lint --e{715}*/
12848  /* the key is the element itself */
12849  return elem;
12850 }
12851 
12852 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12853  * coefficients are either equal or negated
12854  */
12855 static
12856 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12857 {
12858  SCIP* scip;
12859  SCIP_CONSDATA* consdata1;
12860  SCIP_CONSDATA* consdata2;
12861  SCIP_Real cons1scale;
12862  SCIP_Real cons2scale;
12863  int i;
12864 
12865  assert(key1 != NULL);
12866  assert(key2 != NULL);
12867  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12868  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12869  assert(consdata1->sorted);
12870  assert(consdata2->sorted);
12871 
12872  scip = (SCIP*)userptr;
12873  assert(scip != NULL);
12874 
12875  /* if it is the same constraint we dont need to check anything */
12876  if( key1 == key2 )
12877  return TRUE;
12878 
12879  /* checks trivial case */
12880  if( consdata1->nvars != consdata2->nvars )
12881  return FALSE;
12882 
12883  /* tests if variables are equal */
12884  for( i = 0; i < consdata1->nvars; ++i )
12885  {
12886  if( consdata1->vars[i] != consdata2->vars[i] )
12887  {
12888  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12889  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12890  return FALSE;
12891  }
12892  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12893  }
12894 
12895  /* compute scale before comparing coefficients of constraints */
12896  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
12897  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
12898 
12899  /* tests if coefficients are equal with the computed scale */
12900  for( i = 0; i < consdata1->nvars; ++i )
12901  {
12902  SCIP_Real val1;
12903  SCIP_Real val2;
12904 
12905  val1 = consdata1->vals[i] * cons1scale;
12906  val2 = consdata2->vals[i] * cons2scale;
12907 
12908  if( !SCIPisEQ(scip, val1, val2) )
12909  return FALSE;
12910  }
12911 
12912  return TRUE;
12913 }
12914 
12915 /** returns the hash value of the key */
12916 static
12917 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12918 {
12919  SCIP_CONSDATA* consdata;
12920  int minidx;
12921  int mididx;
12922  int maxidx;
12923  SCIP_Real scale;
12924 #ifndef NDEBUG
12925  SCIP* scip;
12926 
12927  scip = (SCIP*)userptr;
12928  assert(scip != NULL);
12929 #endif
12930 
12931  assert(key != NULL);
12932  consdata = SCIPconsGetData((SCIP_CONS*)key);
12933  assert(consdata != NULL);
12934  assert(consdata->nvars > 0);
12935 
12936  assert(consdata->sorted);
12937 
12938  minidx = SCIPvarGetIndex(consdata->vars[0]);
12939  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12940  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12941  assert(minidx >= 0 && minidx <= maxidx);
12942  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
12943 
12944  /* using only the variable indices as hash, since the values are compared by epsilon */
12945  return SCIPhashFour(consdata->nvars,
12946  SCIPcombineTwoInt(minidx, SCIPrealHashCode(consdata->vals[0] * scale)),
12947  SCIPcombineTwoInt(mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale)),
12948  SCIPcombineTwoInt(maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale))); /*lint !e571*/
12949 }
12950 
12951 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12952  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12953  */
12954 static
12955 unsigned int getParallelConsKey(
12956  SCIP_CONS* cons /**< linear constraint */
12957  )
12958 {
12959  SCIP_CONSDATA* consdata;
12960 
12961  assert(cons != NULL);
12962 
12963  consdata = SCIPconsGetData(cons);
12964  assert(consdata != NULL);
12965 
12966  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
12967 }
12968 
12969 /** updates the hashtable such that out of all constraints in the hashtable that are detected
12970  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
12971  * and all others are removed from the hashtable and stored in the given array
12972  */
12973 static
12975  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
12976  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
12977  * upon return will contain the constraint that should be kept */
12978  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
12979  * these constraints where removed from the hashtable */
12980  int* nparallelconss /**< pointer to return number of parallel constraints */
12981  )
12982 {
12983  SCIP_CONS* parallelcons;
12984  unsigned int querykey;
12985 
12986  *nparallelconss = 0;
12987  querykey = getParallelConsKey(*querycons);
12988 
12989  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
12990  {
12991  unsigned int conskey = getParallelConsKey(parallelcons);
12992 
12993  if( conskey < querykey )
12994  {
12995  parallelconss[(*nparallelconss)++] = *querycons;
12996  *querycons = parallelcons;
12997  querykey = conskey;
12998  }
12999  else
13000  {
13001  parallelconss[(*nparallelconss)++] = parallelcons;
13002  }
13003 
13004  /* if the constraint that just came out of the hash table is the one that is kept,
13005  * we do not need to look into the hashtable again, since the invariant is that
13006  * in the hashtable only pair-wise non-parallel constraints are contained.
13007  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13008  * could be contained due to non-transitivity of the equality comparison.
13009  * Also we can return immediately, since parallelcons is already contained in the
13010  * hashtable and we do not need to remove and reinsert it.
13011  */
13012  if( *querycons == parallelcons )
13013  return SCIP_OKAY;
13014 
13015  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13016  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13017  }
13018 
13019  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13020  * comnpares equal to querycons at this point
13021  */
13022 #ifndef NDEBUG
13023  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13024 #else
13025  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13026 #endif
13027 
13028  return SCIP_OKAY;
13029 }
13030 
13031 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13032  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13033  */
13034 static
13036  SCIP* scip, /**< SCIP data structure */
13037  BMS_BLKMEM* blkmem, /**< block memory */
13038  SCIP_CONS** conss, /**< constraint set */
13039  int nconss, /**< number of constraints in constraint set */
13040  int* firstchange, /**< pointer to store first changed constraint */
13041  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13042  int* ndelconss, /**< pointer to count number of deleted constraints */
13043  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13044  )
13045 {
13046  SCIP_HASHTABLE* hashtable;
13047  SCIP_CONS** parallelconss;
13048  int nparallelconss;
13049  int hashtablesize;
13050  int c;
13051 
13052  assert(scip != NULL);
13053  assert(blkmem != NULL);
13054  assert(conss != NULL);
13055  assert(firstchange != NULL);
13056  assert(cutoff != NULL);
13057  assert(ndelconss != NULL);
13058  assert(nchgsides != NULL);
13059 
13060  /* create a hash table for the constraint set */
13061  hashtablesize = nconss;
13062  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13063  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13064 
13065  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13066 
13067  /* check all constraints in the given set for redundancy */
13068  for( c = 0; c < nconss; ++c )
13069  {
13070  SCIP_CONS* cons0;
13071  SCIP_CONSDATA* consdata0;
13072 
13073  cons0 = conss[c];
13074 
13075  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13076  continue;
13077 
13078  /* check for interuption */
13079  if( c % 1000 == 0 && SCIPisStopped(scip) )
13080  break;
13081 
13082  /* sorts the constraint */
13083  consdata0 = SCIPconsGetData(cons0);
13084  assert(consdata0 != NULL);
13085  SCIP_CALL( consdataSort(scip, consdata0) );
13086  assert(consdata0->sorted);
13087 
13088  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13089  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13090  * first variable is positive
13091  * Also inserts cons0 into the hashtable.
13092  */
13093  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13094 
13095  if( nparallelconss != 0 )
13096  {
13097  SCIP_Real lhs;
13098  SCIP_Real rhs;
13099 
13100  int i;
13101 
13102  /* cons0 may have been changed in retrieveParallelConstraints() */
13103  consdata0 = SCIPconsGetData(cons0);
13104 
13105  lhs = consdata0->lhs;
13106  rhs = consdata0->rhs;
13107 
13108  for( i = 0; i < nparallelconss; ++i )
13109  {
13110  SCIP_CONS* consdel;
13111  SCIP_CONSDATA* consdatadel;
13112  SCIP_Real scale;
13113 
13114  consdel = parallelconss[i];
13115  consdatadel = SCIPconsGetData(consdel);
13116 
13117  assert(SCIPconsIsActive(consdel));
13118  assert(!SCIPconsIsModifiable(consdel));
13119 
13120  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13121  * delete old constraints afterwards
13122  */
13123  assert(consdatadel != NULL);
13124  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13125 
13126  assert(consdatadel->sorted);
13127  assert(consdata0->vars[0] == consdatadel->vars[0]);
13128 
13129  scale = consdata0->vals[0] / consdatadel->vals[0];
13130  assert(scale != 0.0);
13131 
13132  /* in debug mode, check that all coefficients are equal with respect to epsilon
13133  * if the constraints are in equilibrium scale
13134  */
13135 #ifndef NDEBUG
13136  {
13137  int k;
13138  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13139  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13140 
13141  for( k = 0; k < consdata0->nvars; ++k )
13142  {
13143  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13144  }
13145  }
13146 #endif
13147 
13148  if( scale > 0.0 )
13149  {
13150  /* the coefficients of both constraints are parallel with a positive scale */
13151  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13152  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13153  SCIPdebugPrintCons(scip, cons0, NULL);
13154  SCIPdebugPrintCons(scip, consdel, NULL);
13155 
13156  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13157  lhs = MAX(scale * consdatadel->lhs, lhs);
13158 
13159  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13160  rhs = MIN(scale * consdatadel->rhs, rhs);
13161  }
13162  else
13163  {
13164  /* the coefficients of both rows are negations */
13165  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13166  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13167  SCIPdebugPrintCons(scip, cons0, NULL);
13168  SCIPdebugPrintCons(scip, consdel, NULL);
13169 
13170  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13171  lhs = MAX(scale * consdatadel->rhs, lhs);
13172 
13173  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13174  rhs = MIN(scale * consdatadel->lhs, rhs);
13175  }
13176 
13177  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13178  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13179 
13180  /* delete consdel */
13181  assert( ! consdata0->upgraded || consdatadel->upgraded );
13182  SCIP_CALL( SCIPdelCons(scip, consdel) );
13183  if( !consdatadel->upgraded )
13184  (*ndelconss)++;
13185  }
13186 
13187  if( SCIPisFeasLT(scip, rhs, lhs) )
13188  {
13189  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13190  *cutoff = TRUE;
13191  break;
13192  }
13193 
13194  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13195  if( lhs > rhs )
13196  {
13197  rhs = (lhs + rhs)/2;
13198  lhs = rhs;
13199  }
13200 
13201  /* update lhs and rhs of cons0 */
13202  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13203  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13204 
13205  /* update the first changed constraint to begin the next aggregation round with */
13206  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13207  *firstchange = SCIPconsGetPos(cons0);
13208 
13209  assert(SCIPconsIsActive(cons0));
13210  }
13211  }
13212 #ifdef SCIP_MORE_DEBUG
13213  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13215 #endif
13216 
13217  SCIPfreeBufferArray(scip, &parallelconss);
13218 
13219  /* free hash table */
13220  SCIPhashtableFree(&hashtable);
13221 
13222  return SCIP_OKAY;
13223 }
13224 
13225 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13226  * and removes or changes constraint accordingly
13227  */
13228 static
13230  SCIP* scip, /**< SCIP data structure */
13231  SCIP_CONS** conss, /**< constraint set */
13232  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13233  int chkind, /**< index of constraint to check against all prior indices upto startind */
13234  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13235  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13236  int* ndelconss, /**< pointer to count number of deleted constraints */
13237  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13238  int* nchgcoefs /**< pointer to count number of changed coefficients */
13239  )
13240 {
13241  SCIP_CONS* cons0;
13242  SCIP_CONSDATA* consdata0;
13243  int* commonidx0;
13244  int* commonidx1;
13245  int* diffidx0minus1;
13246  int* diffidx1minus0;
13247  uint64_t possignature0;
13248  uint64_t negsignature0;
13249  SCIP_Bool cons0changed;
13250  SCIP_Bool cons0isequality;
13251  int diffidx1minus0size;
13252  int c;
13253  SCIP_Real cons0lhs;
13254  SCIP_Real cons0rhs;
13255  SCIP_Bool cons0upgraded;
13256 
13257  assert(scip != NULL);
13258  assert(conss != NULL);
13259  assert(firstchange <= chkind);
13260  assert(cutoff != NULL);
13261  assert(ndelconss != NULL);
13262  assert(nchgsides != NULL);
13263  assert(nchgcoefs != NULL);
13264 
13265  /* get the constraint to be checked against all prior constraints */
13266  cons0 = conss[chkind];
13267  assert(cons0 != NULL);
13268  assert(SCIPconsIsActive(cons0));
13269  assert(!SCIPconsIsModifiable(cons0));
13270 
13271  consdata0 = SCIPconsGetData(cons0);
13272  assert(consdata0 != NULL);
13273  assert(consdata0->nvars >= 1);
13274  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13275 
13276  /* sort the constraint */
13277  SCIP_CALL( consdataSort(scip, consdata0) );
13278 
13279  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13280  consdataCalcSignatures(consdata0);
13281  possignature0 = consdata0->possignature;
13282  negsignature0 = consdata0->negsignature;
13283 
13284  /* get temporary memory for indices of common variables */
13285  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13286  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13287  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13288  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13289  diffidx1minus0size = consdata0->nvars;
13290 
13291  cons0lhs = consdata0->lhs;
13292  cons0rhs = consdata0->rhs;
13293  cons0upgraded = consdata0->upgraded;
13294 
13295  /* check constraint against all prior constraints */
13296  cons0changed = consdata0->changed;
13297  consdata0->changed = FALSE;
13298  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13299  {
13300  SCIP_CONS* cons1;
13301  SCIP_CONSDATA* consdata1;
13302  uint64_t possignature1;
13303  uint64_t negsignature1;
13304  SCIP_Bool cons0dominateslhs;
13305  SCIP_Bool cons1dominateslhs;
13306  SCIP_Bool cons0dominatesrhs;
13307  SCIP_Bool cons1dominatesrhs;
13308  SCIP_Bool cons1isequality;
13309  SCIP_Bool coefsequal;
13310  SCIP_Bool coefsnegated;
13311  SCIP_Bool tryaggregation;
13312  int nvarscommon;
13313  int nvars0minus1;
13314  int nvars1minus0;
13315  int commonidxweight;
13316  int diffidx0minus1weight;
13317  int diffidx1minus0weight;
13318  int v0;
13319  int v1;
13320 
13321  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13322  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13323  assert(cons0upgraded == consdata0->upgraded);
13324 
13325  cons1 = conss[c];
13326 
13327  /* cons1 has become inactive during presolving of constraint pairs */
13328  if( cons1 == NULL )
13329  continue;
13330 
13331  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13332  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13333 
13334  consdata1 = SCIPconsGetData(cons1);
13335  assert(consdata1 != NULL);
13336 
13337  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13338  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13339  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13340 
13341  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13342  if( !cons0changed && !consdata1->changed )
13343  continue;
13344 
13345  /* if both constraints are already upgraded, skip the pair;
13346  * because changes on these constraints cannot be applied to the instance anymore */
13347  if( cons0upgraded && consdata1->upgraded )
13348  continue;
13349 
13350  assert(consdata1->nvars >= 1);
13351 
13352  /* sort the constraint */
13353  SCIP_CALL( consdataSort(scip, consdata1) );
13354 
13355  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13356  consdataCalcSignatures(consdata1);
13357  possignature1 = consdata1->possignature;
13358  negsignature1 = consdata1->negsignature;
13359 
13360  /* the signatures give a quick test to check for domination and equality of coefficients */
13361  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13362  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13363  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13364  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13365  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13366  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13367  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13368  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13369  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13370  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13371  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13372  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13373  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13374  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13375  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13376  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13377  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13378  && !coefsequal && !coefsnegated && !tryaggregation )
13379  continue;
13380 
13381  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13382  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13383  {
13384  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13385  diffidx1minus0size = consdata1->nvars;
13386  }
13387 
13388  /* check consdata0 against consdata1:
13389  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13390  * consdata0 dominates consdata1 w.r.t. left hand side
13391  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13392  * consdata0 dominates consdata1 w.r.t. right hand side
13393  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13394  * ranged row (or equality)
13395  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13396  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13397  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13398  * number of continuous and integer variables are preferred:
13399  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13400  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13401  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13402  * to be positive to not switch the sense of the (in)equality cons0
13403  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13404  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13405  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13406  * to be positive to not switch the sense of the (in)equality cons1
13407  */
13408 
13409  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13410  nvarscommon = 0;
13411  commonidxweight = 0;
13412  nvars0minus1 = 0;
13413  diffidx0minus1weight = 0;
13414  nvars1minus0 = 0;
13415  diffidx1minus0weight = 0;
13416  v0 = 0;
13417  v1 = 0;
13418  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13419  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13420  || coefsequal || coefsnegated || tryaggregation) )
13421  {
13422  SCIP_VAR* var;
13423  SCIP_Real val0;
13424  SCIP_Real val1;
13425  int varcmp;
13426 
13427  /* test, if variable appears in only one or in both constraints */
13428  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13429  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13430  else if( v0 < consdata0->nvars )
13431  varcmp = -1;
13432  else
13433  varcmp = +1;
13434 
13435  switch( varcmp )
13436  {
13437  case -1:
13438  /* variable doesn't appear in consdata1 */
13439  var = consdata0->vars[v0];
13440  val0 = consdata0->vals[v0];
13441  val1 = 0.0;
13442  if( tryaggregation )
13443  {
13444  diffidx0minus1[nvars0minus1] = v0;
13445  nvars0minus1++;
13446  diffidx0minus1weight += getVarWeight(var);
13447  }
13448  v0++;
13449  coefsequal = FALSE;
13450  coefsnegated = FALSE;
13451  break;
13452 
13453  case +1:
13454  /* variable doesn't appear in consdata0 */
13455  var = consdata1->vars[v1];
13456  val0 = 0.0;
13457  val1 = consdata1->vals[v1];
13458  if( tryaggregation )
13459  {
13460  diffidx1minus0[nvars1minus0] = v1;
13461  nvars1minus0++;
13462  diffidx1minus0weight += getVarWeight(var);
13463  }
13464  v1++;
13465  coefsequal = FALSE;
13466  coefsnegated = FALSE;
13467  break;
13468 
13469  case 0:
13470  /* variable appears in both constraints */
13471  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13472  var = consdata0->vars[v0];
13473  val0 = consdata0->vals[v0];
13474  val1 = consdata1->vals[v1];
13475  if( tryaggregation )
13476  {
13477  commonidx0[nvarscommon] = v0;
13478  commonidx1[nvarscommon] = v1;
13479  nvarscommon++;
13480  commonidxweight += getVarWeight(var);
13481  }
13482  v0++;
13483  v1++;
13484  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13485  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13486  break;
13487 
13488  default:
13489  SCIPerrorMessage("invalid comparison result\n");
13490  SCIPABORT();
13491  var = NULL;
13492  val0 = 0.0;
13493  val1 = 0.0;
13494  }
13495  assert(var != NULL);
13496 
13497  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13498  if( SCIPisGT(scip, val0, val1) )
13499  {
13500  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13501  {
13502  cons0dominatesrhs = FALSE;
13503  cons1dominateslhs = FALSE;
13504  }
13505  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13506  {
13507  cons0dominateslhs = FALSE;
13508  cons1dominatesrhs = FALSE;
13509  }
13510  }
13511  else if( SCIPisLT(scip, val0, val1) )
13512  {
13513  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13514  {
13515  cons0dominateslhs = FALSE;
13516  cons1dominatesrhs = FALSE;
13517  }
13518  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13519  {
13520  cons0dominatesrhs = FALSE;
13521  cons1dominateslhs = FALSE;
13522  }
13523  }
13524  }
13525 
13526  /* check for disaggregated ranged rows */
13527  if( coefsequal || coefsnegated )
13528  {
13529  SCIP_CONS* consstay;
13530  SCIP_CONS* consdel;
13531 #ifndef NDEBUG
13532  SCIP_CONSDATA* consdatastay;
13533 #endif
13534  SCIP_CONSDATA* consdatadel;
13535  SCIP_Real lhs;
13536  SCIP_Real rhs;
13537  int consinddel;
13538 
13539  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13540  * best left and right hand sides; delete the old constraints afterwards
13541  */
13542  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13543  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13544  SCIPdebugPrintCons(scip, cons0, NULL);
13545  SCIPdebugPrintCons(scip, cons1, NULL);
13546 
13547  if( coefsequal )
13548  {
13549  /* the coefficients of both rows are equal */
13550  lhs = MAX(consdata0->lhs, consdata1->lhs);
13551  rhs = MIN(consdata0->rhs, consdata1->rhs);
13552  }
13553  else
13554  {
13555  /* the coefficients of both rows are negations */
13556  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13557  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13558  }
13559  if( SCIPisFeasLT(scip, rhs, lhs) )
13560  {
13561  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13562  *cutoff = TRUE;
13563  break;
13564  }
13565 
13566  /* check which constraint has to stay;
13567  * changes applied to an upgraded constraint will not be considered in the instance */
13568  if( consdata0->upgraded )
13569  {
13570  assert(!consdata1->upgraded);
13571  consstay = cons1;
13572 #ifndef NDEBUG
13573  consdatastay = consdata1;
13574 #endif
13575 
13576  consdel = cons0;
13577  consdatadel = consdata0;
13578  consinddel = chkind;
13579  }
13580  else
13581  {
13582  consstay = cons0;
13583 #ifndef NDEBUG
13584  consdatastay = consdata0;
13585 #endif
13586 
13587  consdel = cons1;
13588  consdatadel = consdata1;
13589  consinddel = c;
13590  }
13591 
13592  /* update the sides of consstay */
13593  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13594  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13595  if( !consdata0->upgraded )
13596  {
13597  assert(consstay == cons0);
13598  cons0lhs = consdata0->lhs;
13599  cons0rhs = consdata0->rhs;
13600  }
13601 
13602  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13603  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13604 
13605  assert( !consdatastay->upgraded );
13606  /* delete consdel */
13607  SCIP_CALL( SCIPdelCons(scip, consdel) );
13608  conss[consinddel] = NULL;
13609  if( !consdatadel->upgraded )
13610  (*ndelconss)++;
13611  continue;
13612  }
13613 
13614  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13615  * redundant
13616  */
13617  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13618  {
13619  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13620  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13621  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13622  SCIPdebugPrintCons(scip, cons0, NULL);
13623  SCIPdebugPrintCons(scip, cons1, NULL);
13624 
13625  /* check for infeasibility */
13626  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13627  {
13628  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13629  *cutoff = TRUE;
13630  break;
13631  }
13632 
13633  /* remove redundant left hand side */
13634  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13635  {
13636  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13637  cons0lhs = consdata0->lhs;
13638  cons0isequality = FALSE;
13639  if( !consdata0->upgraded )
13640  {
13641  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13642  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13643 
13644  (*nchgsides)++;
13645  }
13646  }
13647  }
13648  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13649  {
13650  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13651  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13652  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13653  SCIPdebugPrintCons(scip, cons1, NULL);
13654  SCIPdebugPrintCons(scip, cons0, NULL);
13655 
13656  /* check for infeasibility */
13657  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13658  {
13659  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13660  *cutoff = TRUE;
13661  break;
13662  }
13663 
13664  /* remove redundant left hand side */
13665  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13666  {
13667  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13668  cons1isequality = FALSE;
13669  if( !consdata1->upgraded )
13670  {
13671  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13672  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13673 
13674  (*nchgsides)++;
13675  }
13676  }
13677  }
13678  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13679  {
13680  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13681  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13682  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13683  SCIPdebugPrintCons(scip, cons0, NULL);
13684  SCIPdebugPrintCons(scip, cons1, NULL);
13685 
13686  /* check for infeasibility */
13687  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13688  {
13689  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13690  *cutoff = TRUE;
13691  break;
13692  }
13693 
13694  /* remove redundant right hand side */
13695  if( !SCIPisInfinity(scip, consdata0->rhs) )
13696  {
13697  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13698  cons0rhs = consdata0->rhs;
13699  cons0isequality = FALSE;
13700  if( !consdata0->upgraded )
13701  {
13702  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13703  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13704 
13705  (*nchgsides)++;
13706  }
13707  }
13708  }
13709  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13710  {
13711  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13712  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13713  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13714  SCIPdebugPrintCons(scip, cons1, NULL);
13715  SCIPdebugPrintCons(scip, cons0, NULL);
13716 
13717  /* check for infeasibility */
13718  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13719  {
13720  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13721  *cutoff = TRUE;
13722  break;
13723  }
13724 
13725  /* remove redundant right hand side */
13726  if( !SCIPisInfinity(scip, consdata1->rhs) )
13727  {
13728  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13729  cons1isequality = FALSE;
13730  if( !consdata1->upgraded )
13731  {
13732  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13733  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13734 
13735  (*nchgsides)++;
13736  }
13737  }
13738  }
13739 
13740  /* check for now redundant constraints */
13741  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13742  {
13743  /* consdata0 became redundant */
13744  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13745  SCIP_CALL( SCIPdelCons(scip, cons0) );
13746  conss[chkind] = NULL;
13747  if( !consdata0->upgraded )
13748  {
13749  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13750  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13751 
13752  (*ndelconss)++;
13753  }
13754  continue;
13755  }
13756  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13757  {
13758  /* consdata1 became redundant */
13759  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13760  SCIP_CALL( SCIPdelCons(scip, cons1) );
13761  conss[c] = NULL;
13762  if( !consdata1->upgraded )
13763  {
13764  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13765  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13766 
13767  (*ndelconss)++;
13768  }
13769  continue;
13770  }
13771 
13772  /* check, if we want to aggregate an (in)equality with an equality:
13773  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13774  */
13775  if( tryaggregation )
13776  {
13777  SCIP_Bool aggregated;
13778 
13779  assert(consdata0->nvars == nvarscommon + nvars0minus1);
13780  assert(consdata1->nvars == nvarscommon + nvars1minus0);
13781 
13782  aggregated = FALSE;
13783  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13784  {
13785  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13786  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13787  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13788  nchgcoefs, &aggregated, cutoff) );
13789 
13790  if( *cutoff )
13791  break;
13792 
13793  /* update array of active constraints */
13794  if( aggregated )
13795  {
13796  assert(!SCIPconsIsActive(cons0));
13797  assert(SCIPconsIsActive(cons1));
13798  conss[chkind] = NULL;
13799  }
13800  }
13801  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13802  {
13803  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13804  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13805  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13806  nchgcoefs, &aggregated, cutoff) );
13807 
13808  if( *cutoff )
13809  break;
13810 
13811  /* update array of active constraints */
13812  if( aggregated )
13813  {
13814  assert(!SCIPconsIsActive(cons1));
13815  assert(SCIPconsIsActive(cons0));
13816  conss[c] = NULL;
13817  }
13818  }
13819  }
13820  }
13821 
13822  /* free temporary memory */
13823  SCIPfreeBufferArray(scip, &diffidx1minus0);
13824  SCIPfreeBufferArray(scip, &diffidx0minus1);
13825  SCIPfreeBufferArray(scip, &commonidx1);
13826  SCIPfreeBufferArray(scip, &commonidx0);
13827 
13828  return SCIP_OKAY;
13829 }
13830 
13831 /** do stuffing presolving on a single constraint */
13832 static
13834  SCIP* scip, /**< SCIP data structure */
13835  SCIP_CONS* cons, /**< linear constraint */
13836  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13837  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13838  * constraints using the cheapest variable? */
13839  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13840  int* nfixedvars, /**< pointer to count the total number of fixed variables */
13841  int* nchgbds /**< pointer to count the total number of tightened bounds */
13842  )
13843 {
13844  SCIP_CONSDATA* consdata;
13845  SCIP_Real* ratios;
13846  int* varpos;
13847  SCIP_Bool* swapped;
13848  SCIP_VAR** vars;
13849  SCIP_Real* vals;
13850  SCIP_VAR* var;
13851  SCIP_Real lb;
13852  SCIP_Real ub;
13853  SCIP_Real minactivity;
13854  SCIP_Real maxactivity;
13855  SCIP_Real maxcondactivity;
13856  SCIP_Real mincondactivity;
13857  SCIP_Real rhs;
13858  SCIP_Real val;
13859  SCIP_Real obj;
13860  SCIP_Real factor;
13861  SCIP_Bool minactisrelax;
13862  SCIP_Bool maxactisrelax;
13863  SCIP_Bool tryfixing;
13864  int nsingletons;
13865  int idx;
13866  int v;
13867  int nvars;
13868 
13869  assert(scip != NULL);
13870  assert(cons != NULL);
13871  assert(nfixedvars != NULL);
13872 
13873  consdata = SCIPconsGetData(cons);
13874 
13875  /* we only want to run for inequalities */
13876  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13877  return SCIP_OKAY;
13878 
13879  if( singlevarstuffing )
13880  {
13881  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13882  }
13883  else
13884  {
13885  minactivity = SCIP_INVALID;
13886  maxactivity = SCIP_INVALID;
13887  }
13888 
13889  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13890  * the new maxactivity is minus the old minactivity then
13891  */
13892  if( SCIPisInfinity(scip, consdata->rhs) )
13893  {
13894  SCIP_Real tmp;
13895  rhs = -consdata->lhs;
13896  factor = -1.0;
13897  tmp = maxactivity;
13898  maxactivity = -minactivity;
13899  minactivity = -tmp;
13900  }
13901  else
13902  {
13903  assert(SCIPisInfinity(scip, -consdata->lhs));
13904  rhs = consdata->rhs;
13905  factor = 1.0;
13906  }
13907 
13908  nvars = consdata->nvars;
13909  vars = consdata->vars;
13910  vals = consdata->vals;
13911 
13912  /* check for continuous singletons */
13913  if( singletonstuffing )
13914  {
13915  for( v = 0; v < nvars; ++v )
13916  {
13917  var = vars[v];
13918 
13921  break;
13922  }
13923  }
13924  else
13925  /* we don't want to go into the next block */
13926  v = nvars;
13927 
13928  /* a singleton was found -> perform singleton variable stuffing */
13929  if( v < nvars )
13930  {
13931  assert(singletonstuffing);
13932 
13933  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
13934  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
13935  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
13936 
13937  tryfixing = TRUE;
13938  nsingletons = 0;
13939  mincondactivity = 0.0;
13940  maxcondactivity = 0.0;
13941 
13942  for( v = 0; v < nvars; ++v )
13943  {
13944  var = vars[v];
13945  lb = SCIPvarGetLbGlobal(var);
13946  ub = SCIPvarGetUbGlobal(var);
13947  obj = SCIPvarGetObj(var);
13948  val = factor * vals[v];
13949 
13950  assert(!SCIPisZero(scip, val));
13951 
13952  /* the variable is a singleton and continuous */
13955  {
13956  if( SCIPisNegative(scip, obj) && val > 0 )
13957  {
13958  /* case 1: obj < 0 and coef > 0 */
13959  if( SCIPisInfinity(scip, -lb) )
13960  {
13961  tryfixing = FALSE;
13962  break;
13963  }
13964 
13965  maxcondactivity += val * lb;
13966  mincondactivity += val * lb;
13967  swapped[v] = FALSE;
13968  ratios[nsingletons] = obj / val;
13969  varpos[nsingletons] = v;
13970  nsingletons++;
13971  }
13972  else if( SCIPisPositive(scip, obj) && val < 0 )
13973  {
13974  /* case 2: obj > 0 and coef < 0 */
13975  if( SCIPisInfinity(scip, ub) )
13976  {
13977  tryfixing = FALSE;
13978  break;
13979  }
13980  /* multiply column by (-1) to become case 1.
13981  * now bounds are swapped: ub := -lb, lb := -ub
13982  */
13983 
13984  maxcondactivity += val * ub;
13985  mincondactivity += val * ub;
13986  swapped[v] = TRUE;
13987  ratios[nsingletons] = obj / val;
13988  varpos[nsingletons] = v;
13989  nsingletons++;
13990  }
13991  else if( val > 0 )
13992  {
13993  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
13994  * we only consider the lower bound for the constants
13995  */
13996  assert(!SCIPisNegative(scip, obj));
13997 
13998  if( SCIPisInfinity(scip, -lb) )
13999  {
14000  /* maybe unbounded */
14001  tryfixing = FALSE;
14002  break;
14003  }
14004 
14005  maxcondactivity += val * lb;
14006  mincondactivity += val * lb;
14007  }
14008  else
14009  {
14010  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14011  * we only consider the upper bound for the constants
14012  */
14013  assert(!SCIPisPositive(scip, obj));
14014  assert(val < 0);
14015 
14016  if( SCIPisInfinity(scip, ub) )
14017  {
14018  /* maybe unbounded */
14019  tryfixing = FALSE;
14020  break;
14021  }
14022 
14023  maxcondactivity += val * ub;
14024  mincondactivity += val * ub;
14025  }
14026  }
14027  else
14028  {
14029  /* consider contribution of discrete variables, non-singleton
14030  * continuous variables and variables with more than one lock
14031  */
14032  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14033  {
14034  tryfixing = FALSE;
14035  break;
14036  }
14037 
14038  if( val > 0 )
14039  {
14040  maxcondactivity += val * ub;
14041  mincondactivity += val * lb;
14042  }
14043  else
14044  {
14045  maxcondactivity += val * lb;
14046  mincondactivity += val * ub;
14047  }
14048  }
14049  }
14050  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14051  {
14052  SCIP_Real delta;
14053  SCIP_Bool tightened;
14054 #ifdef SCIP_DEBUG
14055  int oldnfixedvars = *nfixedvars;
14056  int oldnchgbds = *nchgbds;
14057 #endif
14058 
14059  SCIPsortRealInt(ratios, varpos, nsingletons);
14060 
14061  /* verify which singleton continuous variables can be fixed */
14062  for( v = 0; v < nsingletons; ++v )
14063  {
14064  idx = varpos[v];
14065  var = vars[idx];
14066  val = factor * vals[idx];
14067  lb = SCIPvarGetLbGlobal(var);
14068  ub = SCIPvarGetUbGlobal(var);
14069 
14070  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14071  assert((val < 0) == swapped[idx]);
14072  val = REALABS(val);
14073 
14074  /* stop fixing if variable bounds are not finite */
14075  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14076  break;
14077 
14080  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14081 
14082  /* calculate the change in the row activities if this variable changes
14083  * its value from its worst to its best bound
14084  */
14085  if( swapped[idx] )
14086  delta = -(lb - ub) * val;
14087  else
14088  delta = (ub - lb) * val;
14089 
14090  assert(!SCIPisNegative(scip, delta));
14091 
14092  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14093  {
14094  if( swapped[idx] )
14095  {
14096  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14097  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14098  }
14099  else
14100  {
14101  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14102  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14103  }
14104 
14105  if( *cutoff )
14106  break;
14107  if( tightened )
14108  {
14109  (*nfixedvars)++;
14110  }
14111  }
14112  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14113  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14114  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14115  * troubles in case of large bounds.
14116  */
14117  else if( SCIPisLE(scip, rhs, mincondactivity) )
14118  {
14119  if( swapped[idx] )
14120  {
14121  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14122  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14123  }
14124  else
14125  {
14126  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14127  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14128  }
14129 
14130  if( *cutoff )
14131  break;
14132  if( tightened )
14133  {
14134  (*nfixedvars)++;
14135  }
14136  }
14137 
14138  maxcondactivity += delta;
14139  mincondactivity += delta;
14140  }
14141 
14142 #ifdef SCIP_DEBUG
14143  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14144  {
14145  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14146  }
14147 #endif
14148  }
14149 
14150  SCIPfreeBufferArray(scip, &swapped);
14151  SCIPfreeBufferArray(scip, &ratios);
14152  SCIPfreeBufferArray(scip, &varpos);
14153  }
14154 
14155  /* perform single-variable stuffing:
14156  * for a linear inequality
14157  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14158  * with a_i > 0 and objective coefficients c_i < 0,
14159  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14160  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14161  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14162  * is redundant.
14163  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14164  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14165  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14166  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14167  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14168  * upper bound.
14169  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14170  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14171  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14172  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14173  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14174  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14175  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14176  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14177  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14178  * c_k * ceil((maxactivity - rhs)/val) is still better than
14179  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14180  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14181  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14182  * sign of coefficients in constraint and objective prevent the use of this method.
14183  */
14184  if( singlevarstuffing && !SCIPisInfinity(scip, -minactivity) )
14185  {
14186  SCIP_Real bestratio = -SCIPinfinity(scip);
14187  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14188  SCIP_Real ratio;
14189  int bestindex = -1;
14190  int bestuplocks = 0;
14191  int bestdownlocks = 1;
14192  int downlocks;
14193  int uplocks;
14194  int oldnfixedvars;
14195  int oldnchgbds;
14196 
14197  SCIPdebug( oldnfixedvars = *nfixedvars; )
14198  SCIPdebug( oldnchgbds = *nchgbds; )
14199  /* loop over all variables to identify the best and second-best ratio */
14200  for( v = 0; v < nvars; ++v )
14201  {
14202  var = vars[v];
14203  obj = SCIPvarGetObj(var);
14204  val = factor * vals[v];
14205 
14206  assert(!SCIPisZero(scip, val));
14207 
14208  ratio = obj / val;
14209 
14210  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14211  if( !SCIPisNegative(scip, ratio) )
14212  {
14213  bestindex = -1;
14214  break;
14215  }
14216 
14217  if( val > 0 )
14218  {
14221  }
14222  else
14223  {
14224  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14226  }
14227 
14228  /* better ratio, update best candidate
14229  * @todo use some tolerance
14230  * @todo check size of domain and updated ratio for integer variables already?
14231  */
14232  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14233  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14234  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14235  {
14236  /* best index becomes second-best*/
14237  if( bestindex != -1 )
14238  {
14239  /* second-best index must not have more than 1 uplock */
14240  if( bestuplocks > 1 )
14241  {
14242  bestindex = -1;
14243  break;
14244  }
14245  else
14246  {
14247  secondbestratio = bestratio;
14248  }
14249  }
14250  bestdownlocks = downlocks;
14251  bestuplocks = uplocks;
14252  bestratio = ratio;
14253  bestindex = v;
14254 
14255  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14256  * if it is not the best, it has too many uplocks -> not applicable
14257  */
14258  if( bestdownlocks > 0 && bestuplocks > 1 )
14259  {
14260  bestindex = -1;
14261  break;
14262  }
14263  }
14264  else
14265  {
14266  /* non-best index must not have more than 1 uplock */
14267  if( uplocks > 1 )
14268  {
14269  bestindex = -1;
14270  break;
14271  }
14272  /* update second-best ratio */
14273  if( ratio > secondbestratio )
14274  {
14275  secondbestratio = ratio;
14276  }
14277  }
14278  }
14279 
14280  /* check if we can apply single variable stuffing */
14281  if( bestindex != -1 && bestdownlocks == 0 )
14282  {
14283  SCIP_Bool tightened = FALSE;
14284  SCIP_Real bounddelta;
14285 
14286  var = vars[bestindex];
14287  obj = SCIPvarGetObj(var);
14288  val = factor * vals[bestindex];
14289  lb = SCIPvarGetLbGlobal(var);
14290  ub = SCIPvarGetUbGlobal(var);
14291  tryfixing = TRUE;
14292 
14293  if( val < 0 )
14294  {
14295  assert(!SCIPisNegative(scip, obj));
14296 
14297  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14298  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14299  {
14300  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14301  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14302  assert(SCIPisPositive(scip, activitydelta));
14303 
14304  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14305 
14306  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14307  assert(SCIPisPositive(scip, bounddelta));
14308  }
14309  else
14310  bounddelta = (maxactivity - rhs)/-val;
14311 
14312  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14313 
14314  if( tryfixing )
14315  {
14316  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14317 
14318  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14319  {
14320  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14321  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14322  }
14323  else
14324  {
14325  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14326  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14327  }
14328  }
14329  }
14330  else
14331  {
14332  assert(!SCIPisPositive(scip, obj));
14333 
14334  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14335  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14336  {
14337  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14338  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14339  assert(SCIPisPositive(scip, activitydelta));
14340 
14341  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14342 
14343  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14344  assert(SCIPisPositive(scip, bounddelta));
14345  }
14346  else
14347  bounddelta = (maxactivity - rhs)/val;
14348 
14349  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14350 
14351  if( tryfixing )
14352  {
14353  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14354 
14355  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14356  {
14357  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14358  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14359  }
14360  else
14361  {
14362  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14363  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14364  }
14365  }
14366  }
14367 
14368  if( *cutoff )
14369  return SCIP_OKAY;
14370  if( tightened )
14371  {
14372  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14373  ++(*nfixedvars);
14374  else
14375  ++(*nchgbds);
14376 
14377  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14378  for( v = 0; v < nvars; ++v )
14379  {
14380  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14381  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14384  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14385  }
14386  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14387 
14388  for( v = 0; v < nvars; ++v )
14389  {
14390  if( v == bestindex )
14391  continue;
14392 
14393  if( factor * vals[v] < 0 )
14394  {
14395  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14396  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14397  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14398  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14399  }
14400  else
14401  {
14402  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14403  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14404  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14405  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14406  }
14407 
14408  if( *cutoff )
14409  return SCIP_OKAY;
14410  if( tightened )
14411  ++(*nfixedvars);
14412  }
14413  SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14414  }
14415  }
14416  }
14417 
14418  return SCIP_OKAY;
14419 }
14420 
14421 /** applies full dual presolving on variables that only appear in linear constraints */
14422 static
14424  SCIP* scip, /**< SCIP data structure */
14425  SCIP_CONS** conss, /**< constraint set */
14426  int nconss, /**< number of constraints */
14427  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14428  int* nchgbds /**< pointer to count the number of bound changes */
14429  )
14430 {
14431  SCIP_Real* redlb;
14432  SCIP_Real* redub;
14433  int* nlocksdown;
14434  int* nlocksup;
14435  SCIP_Bool* isimplint;
14436  SCIP_VAR** origvars;
14437  SCIP_VAR** vars;
14438  SCIP_VAR** conscontvars;
14439  int nvars;
14440  int nbinvars;
14441  int nintvars;
14442  int ncontvars;
14443  int v;
14444  int c;
14445 
14446  /* we calculate redundancy bounds with the following meaning:
14447  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14448  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14449  * then:
14450  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14451  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14452  */
14453 
14454  /* Additionally, we detect continuous variables that are implicitly integral.
14455  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14456  * and all constraints (including the bounds as trivial constraints) in which:
14457  * c_j > 0: the variable is down-locked,
14458  * c_j < 0: the variable is up-locked,
14459  * c_j = 0: the variable appears
14460  * have, apart from j, only integer variables with integral coefficients and integral sides.
14461  * This is because then, the value of the variable is either determined by one of its bounds or
14462  * by one of these constraints, and in all cases, the value of the variable is integral.
14463  */
14464 
14465  assert(scip != NULL);
14466  assert(nconss == 0 || conss != NULL);
14467  assert(nchgbds != NULL);
14468  assert(!SCIPinProbing(scip));
14469 
14470  /* get active variables */
14471  nvars = SCIPgetNVars(scip);
14472  origvars = SCIPgetVars(scip);
14473 
14474  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14475  nbinvars = SCIPgetNBinVars(scip);
14476  if( nbinvars == nvars )
14477  return SCIP_OKAY;
14478 
14479  /* get number of continuous variables */
14480  ncontvars = SCIPgetNContVars(scip);
14481  nintvars = nvars - ncontvars;
14482 
14483  /* copy the variable array since this array might change during the curse of this algorithm */
14484  nvars = nvars - nbinvars;
14485  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14486 
14487  /* allocate temporary memory */
14488  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14489  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14490  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14491  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14492  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14493  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14494 
14495  /* initialize redundancy bounds */
14496  for( v = 0; v < nvars; ++v )
14497  {
14498  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14499  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14500  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14501  }
14502  BMSclearMemoryArray(nlocksdown, nvars);
14503  BMSclearMemoryArray(nlocksup, nvars);
14504 
14505  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14506  * We better not use SCIPisFeasIntegral() in these checks.
14507  */
14508  for( v = 0; v < ncontvars; v++ )
14509  {
14510  SCIP_VAR* var;
14511  SCIP_Real obj;
14512  SCIP_Real lb;
14513  SCIP_Real ub;
14514 
14515  var = vars[v + nintvars - nbinvars];
14516  lb = SCIPvarGetLbGlobal(var);
14517  ub = SCIPvarGetUbGlobal(var);
14518 
14519  obj = SCIPvarGetObj(var);
14520  if( SCIPisZero(scip, obj) )
14521  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14522  else
14523  {
14524  if( SCIPisPositive(scip, obj) )
14525  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14526  else
14527  {
14528  assert(SCIPisNegative(scip, obj));
14529  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14530  }
14531  }
14532  }
14533 
14534  /* scan all constraints */
14535  for( c = 0; c < nconss; ++c )
14536  {
14537  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14538  * part of checked disjunctions)
14539  */
14540  if( SCIPconsIsLocked(conss[c]) )
14541  {
14542  SCIP_CONSDATA* consdata;
14543  SCIP_Bool lhsexists;
14544  SCIP_Bool rhsexists;
14545  SCIP_Bool hasimpliedpotential;
14546  SCIP_Bool integralcoefs;
14547  int nlockspos;
14548  int contvarpos;
14549  int nconscontvars;
14550  int i;
14551 
14552  consdata = SCIPconsGetData(conss[c]);
14553  assert(consdata != NULL);
14554 
14555  /* get number of times the constraint was locked */
14556  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14557 
14558  /* we do not want to include constraints with locked negation (this would be too weird) */
14559  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14560  {
14561  /* mark all continuous variables as not being implicit integral */
14562  for( i = 0; i < consdata->nvars; ++i )
14563  {
14564  SCIP_VAR* var;
14565 
14566  var = consdata->vars[i];
14568  {
14569  int contv;
14570  contv = SCIPvarGetProbindex(var) - nintvars;
14571  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14572  isimplint[contv] = FALSE;
14573  }
14574  }
14575  continue;
14576  }
14577 
14578  /* check for existing sides */
14579  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14580  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14581 
14582  /* count locks and update redundancy bounds */
14583  contvarpos = -1;
14584  nconscontvars = 0;
14585  hasimpliedpotential = FALSE;
14586  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14587 
14588  for( i = 0; i < consdata->nvars; ++i )
14589  {
14590  SCIP_VAR* var;
14591  SCIP_Real val;
14592  SCIP_Real minresactivity;
14593  SCIP_Real maxresactivity;
14594  SCIP_Real newredlb;
14595  SCIP_Real newredub;
14596  SCIP_Bool minisrelax;
14597  SCIP_Bool maxisrelax;
14598  SCIP_Bool isminsettoinfinity;
14599  SCIP_Bool ismaxsettoinfinity;
14600  int arrayindex;
14601 
14602  var = consdata->vars[i];
14603  val = consdata->vals[i];
14604 
14605  /* check if still all integer variables have integral coefficients */
14606  if( SCIPvarIsIntegral(var) )
14607  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14608 
14609  /* we do not need to process binary variables */
14610  if( SCIPvarIsBinary(var) )
14611  continue;
14612 
14613  if( SCIPconsIsModifiable(conss[c]) )
14614  {
14615  minresactivity = -SCIPinfinity(scip);
14616  maxresactivity = SCIPinfinity(scip);
14617  isminsettoinfinity = TRUE;
14618  ismaxsettoinfinity = TRUE;
14619  }
14620  else
14621  {
14622  /* calculate residual activity bounds if variable would be fixed to zero */
14623  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14624  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14625 
14626  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14627  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14628  * This is needed, because we do not want to rely on relaxed finite resactivities.
14629  */
14630  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14631 
14632  /* check minresactivity for reliability */
14633  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14634  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14635 
14636  /* check maxresactivity for reliability */
14637  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14638  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14639  }
14640 
14641  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14642 
14643  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14644 
14645  newredlb = redlb[arrayindex];
14646  newredub = redub[arrayindex];
14647  if( val > 0.0 )
14648  {
14649  if( lhsexists )
14650  {
14651  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14652  nlocksdown[arrayindex] += nlockspos;
14653  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14654  }
14655  if( rhsexists )
14656  {
14657  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14658  nlocksup[arrayindex] += nlockspos;
14659  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14660  }
14661  }
14662  else
14663  {
14664  if( lhsexists )
14665  {
14666  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14667  nlocksup[arrayindex] += nlockspos;
14668  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14669  }
14670  if( rhsexists )
14671  {
14672  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14673  nlocksdown[arrayindex] += nlockspos;
14674  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14675  }
14676  }
14677 
14678  /* if the variable is integer, we have to round the value to the next integral value */
14679  if( SCIPvarIsIntegral(var) )
14680  {
14681  if( !SCIPisInfinity(scip, newredlb) )
14682  newredlb = SCIPceil(scip, newredlb);
14683  if( !SCIPisInfinity(scip, -newredub) )
14684  newredub = SCIPfloor(scip, newredub);
14685  }
14686 
14687  /* update redundancy bounds */
14688  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14689  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14690 
14691  /* collect the continuous variables of the constraint */
14693  {
14694  int contv;
14695 
14696  assert(nconscontvars < ncontvars);
14697  contvarpos = i;
14698  conscontvars[nconscontvars] = var;
14699  nconscontvars++;
14700 
14701  contv = SCIPvarGetProbindex(var) - nintvars;
14702  assert(0 <= contv && contv < ncontvars);
14703  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14704  }
14705  }
14706 
14707  /* update implied integer status of continuous variables */
14708  if( hasimpliedpotential )
14709  {
14710  if( nconscontvars > 1 || !integralcoefs )
14711  {
14712  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14713  * none of the continuous variables is implied integer
14714  */
14715  for( i = 0; i < nconscontvars; i++ )
14716  {
14717  int contv;
14718  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14719  assert(0 <= contv && contv < ncontvars);
14720  isimplint[contv] = FALSE;
14721  }
14722  }
14723  else
14724  {
14725  SCIP_VAR* var;
14726  SCIP_Real val;
14727  SCIP_Real absval;
14728  int contv;
14729 
14730  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14731  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14732  * side(s) of the constraint is integral
14733  */
14734  assert(nconscontvars == 1);
14735  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14736  var = consdata->vars[contvarpos];
14737  val = consdata->vals[contvarpos];
14738  contv = SCIPvarGetProbindex(var) - nintvars;
14739  assert(0 <= contv && contv < ncontvars);
14740  assert(isimplint[contv]);
14741 
14742  absval = REALABS(val);
14743  if( !SCIPisEQ(scip, absval, 1.0) )
14744  isimplint[contv] = FALSE;
14745  else
14746  {
14747  SCIP_Real obj;
14748 
14749  obj = SCIPvarGetObj(var);
14750  if( obj * val >= 0.0 && lhsexists )
14751  {
14752  /* the variable may be blocked by the constraint's left hand side */
14753  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14754  }
14755  if( obj * val <= 0.0 && rhsexists )
14756  {
14757  /* the variable may be blocked by the constraint's left hand side */
14758  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14759  }
14760  }
14761  }
14762  }
14763  }
14764  }
14765 
14766  /* check if any bounds can be tightened due to optimality */
14767  for( v = 0; v < nvars; ++v )
14768  {
14769  SCIP_VAR* var;
14770  SCIP_Real obj;
14771  SCIP_Bool infeasible;
14772  SCIP_Bool tightened;
14773 
14774  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14775  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14776  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14777 
14778  var = vars[v];
14779  obj = SCIPvarGetObj(var);
14780  if( obj >= 0.0 )
14781  {
14782  /* making the variable as small as possible does not increase the objective:
14783  * check if all down locks of the variables are due to linear constraints;
14784  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14785  */
14786  if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14787  && !SCIPisInfinity(scip, -redlb[v])
14788  && redlb[v] < SCIPvarGetUbGlobal(var) )
14789  {
14790  SCIP_Real ub;
14791 
14792  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14793  * -> tighten upper bound to x_v <= redlb[v]
14794  */
14795  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14797  redlb[v]);
14798  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14799  assert(!infeasible);
14800 
14801  ub = SCIPvarGetUbGlobal(var);
14802  redub[v] = MIN(redub[v], ub);
14803  if( tightened )
14804  (*nchgbds)++;
14805  }
14806  }
14807  if( obj <= 0.0 )
14808  {
14809  /* making the variable as large as possible does not increase the objective:
14810  * check if all up locks of the variables are due to linear constraints;
14811  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14812  */
14813  if( SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14814  && !SCIPisInfinity(scip, redub[v])
14815  && redub[v] > SCIPvarGetLbGlobal(var) )
14816  {
14817  SCIP_Real lb;
14818 
14819  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14820  * -> tighten lower bound to x_v >= redub[v]
14821  */
14822  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14824  redub[v]);
14825  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14826  assert(!infeasible);
14827 
14828  lb = SCIPvarGetLbGlobal(var);
14829  redlb[v] = MAX(redlb[v], lb);
14830  if( tightened )
14831  (*nchgbds)++;
14832  }
14833  }
14834  }
14835 
14836  /* upgrade continuous variables to implied integers */
14837  for( v = nintvars - nbinvars; v < nvars; ++v )
14838  {
14839  SCIP_VAR* var;
14840  SCIP_Bool infeasible;
14841 
14842  var = vars[v];
14843  assert(var != NULL);
14844 
14845  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14846  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14847  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14848  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14849 
14850  /* we can only conclude implied integrality if the variable appears in no other constraint */
14851  if( isimplint[v - nintvars + nbinvars]
14852  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14853  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
14854  {
14855  /* since we locally copied the variable array we can change the variable type immediately */
14856  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
14857 
14858  if( infeasible )
14859  {
14860  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14861  *cutoff = TRUE;
14862 
14863  break;
14864  }
14865 
14866  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
14868  }
14869  }
14870 
14871  /* free temporary memory */
14872  SCIPfreeBufferArray(scip, &conscontvars);
14873  SCIPfreeBufferArray(scip, &isimplint);
14874  SCIPfreeBufferArray(scip, &nlocksup);
14875  SCIPfreeBufferArray(scip, &nlocksdown);
14876  SCIPfreeBufferArray(scip, &redub);
14877  SCIPfreeBufferArray(scip, &redlb);
14878 
14879  SCIPfreeBufferArray(scip, &vars);
14880 
14881  return SCIP_OKAY;
14882 }
14883 
14884 /** helper function to enforce constraints */
14885 static
14887  SCIP* scip, /**< SCIP data structure */
14888  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14889  SCIP_CONS** conss, /**< constraints to process */
14890  int nconss, /**< number of constraints */
14891  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14892  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14893  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14894  )
14895 {
14896  SCIP_CONSHDLRDATA* conshdlrdata;
14897  SCIP_Bool checkrelmaxabs;
14898  SCIP_Bool violated;
14899  SCIP_Bool cutoff = FALSE;
14900  int c;
14901 
14902  assert(scip != NULL);
14903  assert(conshdlr != NULL);
14904  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14905  assert(result != NULL);
14906 
14907  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14908  assert(conshdlrdata != NULL);
14909 
14910  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14911 
14912  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14913 
14914  /* check for violated constraints
14915  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14916  */
14917  *result = SCIP_FEASIBLE;
14918 
14919  /* check all useful linear constraints for feasibility */
14920  for( c = 0; c < nusefulconss; ++c )
14921  {
14922  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14923 
14924  if( violated )
14925  {
14926  /* insert LP row as cut */
14927  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14928  if ( cutoff )
14929  *result = SCIP_CUTOFF;
14930  else
14931  *result = SCIP_SEPARATED;
14932  }
14933  }
14934 
14935  /* check all obsolete linear constraints for feasibility */
14936  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14937  {
14938  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14939 
14940  if( violated )
14941  {
14942  /* insert LP row as cut */
14943  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14944  if ( cutoff )
14945  *result = SCIP_CUTOFF;
14946  else
14947  *result = SCIP_SEPARATED;
14948  }
14949  }
14950 
14951  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
14952 
14953  return SCIP_OKAY;
14954 }
14955 
14956 /*
14957  * Callback methods of constraint handler
14958  */
14959 
14960 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
14961 static
14962 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
14963 { /*lint --e{715}*/
14964  assert(scip != NULL);
14965  assert(conshdlr != NULL);
14966  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14967 
14968  /* call inclusion method of constraint handler */
14970 
14971  *valid = TRUE;
14972 
14973  return SCIP_OKAY;
14974 }
14975 
14976 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
14977 static
14978 SCIP_DECL_CONSFREE(consFreeLinear)
14979 { /*lint --e{715}*/
14980  SCIP_CONSHDLRDATA* conshdlrdata;
14981 
14982  assert(scip != NULL);
14983  assert(conshdlr != NULL);
14984  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14985 
14986  /* free constraint handler data */
14987  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14988  assert(conshdlrdata != NULL);
14989 
14990  conshdlrdataFree(scip, &conshdlrdata);
14991 
14992  SCIPconshdlrSetData(conshdlr, NULL);
14993 
14994  return SCIP_OKAY;
14996 
14997 
14998 /** initialization method of constraint handler (called after problem was transformed) */
14999 static
15000 SCIP_DECL_CONSINIT(consInitLinear)
15001 {
15002  SCIP_CONSHDLRDATA* conshdlrdata;
15003  int c;
15004 
15005  assert(scip != NULL);
15006 
15007  /* check for event handler */
15008  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15009  assert(conshdlrdata != NULL);
15010  assert(conshdlrdata->eventhdlr != NULL);
15011  assert(nconss == 0 || conss != NULL);
15012 
15013  /* catch events for the constraints */
15014  for( c = 0; c < nconss; ++c )
15015  {
15016  /* catch all events */
15017  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15018  }
15019 
15020  return SCIP_OKAY;
15021 }
15022 
15023 
15024 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15025 static
15026 SCIP_DECL_CONSEXIT(consExitLinear)
15027 {
15028  SCIP_CONSHDLRDATA* conshdlrdata;
15029  int c;
15030 
15031  assert(scip != NULL);
15032 
15033  /* check for event handler */
15034  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15035  assert(conshdlrdata != NULL);
15036  assert(conshdlrdata->eventhdlr != NULL);
15037 
15038  /* drop events for the constraints */
15039  for( c = nconss - 1; c >= 0; --c )
15040  {
15041  SCIP_CONSDATA* consdata;
15042 
15043  consdata = SCIPconsGetData(conss[c]);
15044  assert(consdata != NULL);
15045 
15046  if( consdata->eventdata != NULL )
15047  {
15048  /* drop all events */
15049  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15050  assert(consdata->eventdata == NULL);
15051  }
15052  }
15053 
15054  return SCIP_OKAY;
15055 }
15056 
15057 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15058 static
15060  SCIP* scip, /**< SCIP data structure */
15061  SCIP_Real lhs, /**< left hand side */
15062  SCIP_Real rhs /**< right hand side */
15063  )
15064 {
15065  assert(scip != NULL);
15066 
15067  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15068 }
15069 
15070 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15071 static
15073  SCIP* scip, /**< SCIP data structure */
15074  SCIP_Real x /**< value */
15075  )
15077  assert(scip != NULL);
15078 
15079  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15080 }
15081 
15082 /** performs linear constraint type classification as used for MIPLIB
15083  *
15084  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15085  *
15086  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15087  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15088  * Similarly, if specialized constraints were created through the API, these are currently not present.
15089  */
15091  SCIP* scip, /**< SCIP data structure */
15092  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15093  )
15094 {
15095  int c;
15096  SCIP_CONSHDLR* conshdlr;
15097  SCIP_CONS** conss;
15098  int nconss;
15099 
15100  assert(scip != NULL);
15101  assert(linconsstats != NULL);
15102  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15103  assert(conshdlr != NULL);
15104 
15105  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15106  {
15107  conss = SCIPgetConss(scip);
15108  nconss = SCIPgetNConss(scip);
15109  }
15110  else
15111  {
15112  conss = SCIPconshdlrGetConss(conshdlr);
15113  nconss = SCIPconshdlrGetNConss(conshdlr);
15114  }
15115 
15116  /* reset linear constraint type classification */
15117  SCIPlinConsStatsReset(linconsstats);
15118 
15119  /* loop through all constraints */
15120  for( c = 0; c < nconss; c++ )
15121  {
15122  SCIP_CONS* cons;
15123  SCIP_CONSDATA* consdata;
15124  SCIP_Real lhs;
15125  SCIP_Real rhs;
15126  int i;
15127 
15128  /* get constraint */
15129  cons = conss[c];
15130  assert(cons != NULL);
15131 
15132  /* skip constraints that are not handled by the constraint handler */
15133  if( SCIPconsGetHdlr(cons) != conshdlr )
15134  continue;
15135 
15136  /* get constraint data */
15137  consdata = SCIPconsGetData(cons);
15138  assert(consdata != NULL);
15139  rhs = consdata->rhs;
15140  lhs = consdata->lhs;
15141 
15142  /* merge multiples and delete variables with zero coefficient */
15143  SCIP_CALL( mergeMultiples(scip, cons) );
15144  for( i = 0; i < consdata->nvars; i++ )
15145  {
15146  assert(!SCIPisZero(scip, consdata->vals[i]));
15147  }
15148 
15149  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15150  if( consdata->nvars == 0 )
15151  {
15152  SCIPdebugMsg(scip, "classified as EMPTY: ");
15153  SCIPdebugPrintCons(scip, cons, NULL);
15155 
15156  continue;
15157  }
15158 
15159  /* is constraint of type SCIP_CONSTYPE_FREE? */
15160  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15161  {
15162  SCIPdebugMsg(scip, "classified as FREE: ");
15163  SCIPdebugPrintCons(scip, cons, NULL);
15165 
15166  continue;
15167  }
15168 
15169  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15170  if( consdata->nvars == 1 )
15171  {
15172  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15173  SCIPdebugPrintCons(scip, cons, NULL);
15174  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15175 
15176  continue;
15177  }
15178 
15179  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15180  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15181  {
15182  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15183  SCIPdebugPrintCons(scip, cons, NULL);
15185 
15186  continue;
15187  }
15188 
15189  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15190  if( consdata->nvars == 2 )
15191  {
15192  SCIP_LINCONSTYPE constype;
15193 
15194  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15195  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15196  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15197  {
15198  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15199  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15200  }
15201  else
15202  {
15203  constype = SCIP_LINCONSTYPE_VARBOUND;
15204  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15205  }
15206  SCIPdebugPrintCons(scip, cons, NULL);
15207 
15208  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15209 
15210  continue;
15211  }
15212 
15213  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15214  {
15215  SCIP_Real scale;
15216  SCIP_Real b;
15217  SCIP_Bool unmatched;
15218  int nnegbinvars;
15219 
15220  unmatched = FALSE;
15221  nnegbinvars = 0;
15222 
15223  scale = REALABS(consdata->vals[0]);
15224 
15225  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15226  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15227  {
15228  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15229  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15230  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15231  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15232 
15233  if( consdata->vals[i] < 0.0 )
15234  nnegbinvars++;
15235  }
15236 
15237  if( !unmatched )
15238  {
15239  if( SCIPisEQ(scip, lhs, rhs) )
15240  {
15241  b = rhs/scale + nnegbinvars;
15242  if( SCIPisEQ(scip, 1.0, b) )
15243  {
15244  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15245  SCIPdebugPrintCons(scip, cons, NULL);
15247 
15248  continue;
15249  }
15250  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15251  {
15252  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15253  SCIPdebugPrintCons(scip, cons, NULL);
15255 
15256  continue;
15257  }
15258  }
15259 
15260  /* compute right hand side divided by scale */
15261  if( !SCIPisInfinity(scip, rhs) )
15262  b = rhs/scale + nnegbinvars;
15263  else
15264  b = SCIPinfinity(scip);
15265 
15266  if( SCIPisEQ(scip, 1.0, b) )
15267  {
15268  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15269  SCIPdebugPrintCons(scip, cons, NULL);
15271 
15272  /* relax right hand side to prevent further classifications */
15273  rhs = SCIPinfinity(scip);
15274  }
15275  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15276  {
15277  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15278  SCIPdebugPrintCons(scip, cons, NULL);
15279 
15281 
15282  /* relax right hand side to prevent further classifications */
15283  rhs = SCIPinfinity(scip);
15284  }
15285 
15286  if( !SCIPisInfinity(scip, lhs) )
15287  b = lhs/scale + nnegbinvars;
15288  else
15289  b = SCIPinfinity(scip);
15290 
15291  if( SCIPisEQ(scip, 1.0, b) )
15292  {
15293  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15294  SCIPdebugPrintCons(scip, cons, NULL);
15296 
15297  /* relax left hand side to prevent further classifications */
15298  lhs = -SCIPinfinity(scip);
15299  }
15300 
15301  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15302  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15303  continue;
15304  }
15305  }
15306 
15307  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15308  /* @todo If coefficients or rhs are not integral, we currently do not check
15309  * if the constraint could be scaled (finitely), such that they are.
15310  */
15311  {
15312  SCIP_Real b;
15313  SCIP_Bool unmatched;
15314 
15315  b = rhs;
15316  unmatched = FALSE;
15317  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15318  {
15319  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15320  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15321  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15322  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15323 
15324  if( SCIPisNegative(scip, consdata->vals[i]) )
15325  b -= consdata->vals[i];
15326  }
15327  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15328 
15329  if( !unmatched )
15330  {
15331  if( SCIPisEQ(scip, lhs, rhs) )
15332  {
15333  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15334  SCIPdebugPrintCons(scip, cons, NULL);
15335 
15337 
15338  continue;
15339  }
15340  else
15341  {
15342  SCIP_Bool matched;
15343 
15344  matched = FALSE;
15345  for( i = 0; i < consdata->nvars && !matched; i++ )
15346  {
15347  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15348  }
15349 
15350  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15351  SCIPdebugPrintCons(scip, cons, NULL);
15353  }
15354 
15355  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15356  if( SCIPisInfinity(scip, -lhs) )
15357  continue;
15358  else
15359  rhs = SCIPinfinity(scip);
15360  }
15361  }
15362 
15363  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15364  {
15365  SCIP_Real b;
15366  SCIP_Bool unmatched;
15367 
15368  unmatched = FALSE;
15369 
15370  b = rhs;
15371  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15372 
15373  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15374  {
15375  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15376  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15377  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15378  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15379  }
15380 
15381  if( !unmatched )
15382  {
15383  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15384  SCIPdebugPrintCons(scip, cons, NULL);
15386 
15387  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15388  if( SCIPisInfinity(scip, -lhs) )
15389  continue;
15390  else
15391  rhs = SCIPinfinity(scip);
15392  }
15393  }
15394 
15395  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15396  {
15397  SCIP_Bool unmatched;
15398 
15399  unmatched = FALSE;
15400  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15401  {
15402  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15403  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15404  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15405  unmatched = TRUE;
15406  }
15407 
15408  if( !unmatched )
15409  {
15410  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15411  SCIPdebugPrintCons(scip, cons, NULL);
15412  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15413 
15414  continue;
15415  }
15416  }
15417 
15418  /* no special structure detected */
15419  SCIPdebugMsg(scip, "classified as GENERAL: ");
15420  SCIPdebugPrintCons(scip, cons, NULL);
15421  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15422  }
15423 
15424  return SCIP_OKAY;
15425 }
15426 
15427 
15428 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15429 static
15430 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15431 { /*lint --e{715}*/
15432  int c;
15433 #ifdef SCIP_STATISTIC
15434  SCIP_CONSHDLRDATA* conshdlrdata;
15435  int ngoodconss;
15436  int nallconss;
15437 #endif
15438 
15439  /* delete all linear constraints that were upgraded to a more specific constraint type;
15440  * make sure, only active variables remain in the remaining constraints
15441  */
15442  assert(scip != NULL);
15443 
15444 #ifdef SCIP_STATISTIC
15445  /* count number of well behaved linear constraints */
15446  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15447  assert(conshdlrdata != NULL);
15448 
15449  ngoodconss = 0;
15450  nallconss = 0;
15451 
15452  for( c = 0; c < nconss; ++c )
15453  {
15454  SCIP_CONSDATA* consdata;
15455 
15456  if( SCIPconsIsDeleted(conss[c]) )
15457  continue;
15458 
15459  consdata = SCIPconsGetData(conss[c]);
15460  assert(consdata != NULL);
15461 
15462  if( consdata->upgraded )
15463  continue;
15464 
15465  nallconss++;
15466 
15467  consdataRecomputeMaxActivityDelta(scip, consdata);
15468 
15469  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15470  ngoodconss++;
15471  }
15472  if( nallconss )
15473  {
15474  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15475  }
15476 #endif
15477 
15478  for( c = 0; c < nconss; ++c )
15479  {
15480  SCIP_CONSDATA* consdata;
15481 
15482  if( SCIPconsIsDeleted(conss[c]) )
15483  continue;
15484 
15485  consdata = SCIPconsGetData(conss[c]);
15486  assert(consdata != NULL);
15487 
15488  if( consdata->upgraded )
15489  {
15490  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15491  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15492  */
15493  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15494  }
15495  else
15496  {
15497  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15498  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15499  }
15500  }
15501 
15502  return SCIP_OKAY;
15503 }
15504 
15505 
15506 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15507 static
15508 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15509 { /*lint --e{715}*/
15510  int c;
15511 
15512  assert(scip != NULL);
15513 
15514  /* release the rows of all constraints */
15515  for( c = 0; c < nconss; ++c )
15516  {
15517  SCIP_CONSDATA* consdata;
15518 
15519  consdata = SCIPconsGetData(conss[c]);
15520  assert(consdata != NULL);
15521 
15522  if( consdata->row != NULL )
15523  {
15524  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15525  }
15526  }
15527 
15528  /* if this is a restart, convert cutpool rows into linear constraints */
15529  if( restart )
15530  {
15531  int ncutsadded;
15532 
15533  ncutsadded = 0;
15534 
15535  /* create out of all active cuts in cutpool linear constraints */
15536  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15537 
15538  if( ncutsadded > 0 )
15539  {
15541  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15542  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15543  * line correctly
15544  */
15546  }
15547  }
15548 
15549  return SCIP_OKAY;
15550 }
15551 
15552 
15553 /** constraint deactivation notification method of constraint handler */
15554 static
15555 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15556 { /*lint --e{715}*/
15557  assert( cons != NULL );
15558 
15559  if( SCIPconsIsDeleted(cons) )
15560  {
15561  SCIP_CONSHDLRDATA* conshdlrdata;
15562  SCIP_CONSDATA* consdata;
15563 
15564  assert(scip != NULL);
15565  assert(conshdlr != NULL);
15566  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15567 
15568  /* get constraint data */
15569  consdata = SCIPconsGetData(cons);
15570  assert(consdata != NULL);
15571 
15572  /* check for event handler */
15573  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15574  assert(conshdlrdata != NULL);
15575  assert(conshdlrdata->eventhdlr != NULL);
15576 
15577  /* free event data */
15578  if( consdata->eventdata != NULL )
15579  {
15580  /* drop bound change events of variables */
15581  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15582  }
15583  assert(consdata->eventdata == NULL);
15584  }
15585 
15586  return SCIP_OKAY;
15587 }
15588 
15589 
15590 /** frees specific constraint data */
15591 static
15592 SCIP_DECL_CONSDELETE(consDeleteLinear)
15593 { /*lint --e{715}*/
15594  assert(scip != NULL);
15595  assert(conshdlr != NULL);
15596  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15597 
15598  if( (*consdata)->eventdata != NULL )
15599  {
15600  SCIP_CONSHDLRDATA* conshdlrdata;
15601 
15602  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15603  assert(conshdlrdata != NULL);
15604 
15605  /* drop all events */
15606  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15607  assert((*consdata)->eventdata == NULL);
15608  }
15610  /* free linear constraint */
15611  SCIP_CALL( consdataFree(scip, consdata) );
15612 
15613  return SCIP_OKAY;
15614 }
15615 
15616 
15617 /** transforms constraint data into data belonging to the transformed problem */
15618 static
15619 SCIP_DECL_CONSTRANS(consTransLinear)
15620 { /*lint --e{715}*/
15621  SCIP_CONSDATA* sourcedata;
15622  SCIP_CONSDATA* targetdata;
15623 
15624  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15625 
15626  assert(scip != NULL);
15627  assert(conshdlr != NULL);
15628  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15629  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15630  assert(sourcecons != NULL);
15631  assert(targetcons != NULL);
15632 
15633  sourcedata = SCIPconsGetData(sourcecons);
15634  assert(sourcedata != NULL);
15635  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15637  /* create linear constraint data for target constraint */
15638  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15639 
15640  /* create target constraint */
15641  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15642  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15643  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15644  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15645  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15646 
15647  return SCIP_OKAY;
15648 }
15649 
15650 
15651 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15652 static
15653 SCIP_DECL_CONSINITLP(consInitlpLinear)
15654 { /*lint --e{715}*/
15655  int c;
15656 
15657  assert(scip != NULL);
15658  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15659 
15660  *infeasible = FALSE;
15661 
15662  for( c = 0; c < nconss && !(*infeasible); ++c )
15663  {
15664  assert(SCIPconsIsInitial(conss[c]));
15665  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15666  }
15667 
15668  return SCIP_OKAY;
15669 }
15671 
15672 /** separation method of constraint handler for LP solutions */
15673 static
15674 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15675 { /*lint --e{715}*/
15676  SCIP_CONSHDLRDATA* conshdlrdata;
15677  SCIP_Real loclowerbound;
15678  SCIP_Real glblowerbound;
15679  SCIP_Real cutoffbound;
15680  SCIP_Real maxbound;
15681  SCIP_Bool separatecards;
15682  SCIP_Bool cutoff;
15683  int c;
15684  int depth;
15685  int nrounds;
15686  int maxsepacuts;
15687  int ncuts;
15688 
15689  assert(scip != NULL);
15690  assert(conshdlr != NULL);
15691  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15692  assert(result != NULL);
15693 
15694  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15695  assert(conshdlrdata != NULL);
15696  depth = SCIPgetDepth(scip);
15697  nrounds = SCIPgetNSepaRounds(scip);
15698 
15699  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15700 
15701  *result = SCIP_DIDNOTRUN;
15702 
15703  /* only call the separator a given number of times at each node */
15704  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15705  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15706  return SCIP_OKAY;
15707 
15708  /* get the maximal number of cuts allowed in a separation round */
15709  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15710 
15711  /* check if we want to produce knapsack cardinality cuts at this node */
15712  loclowerbound = SCIPgetLocalLowerbound(scip);
15713  glblowerbound = SCIPgetLowerbound(scip);
15714  cutoffbound = SCIPgetCutoffbound(scip);
15715  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15716  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15717  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15718 
15719  *result = SCIP_DIDNOTFIND;
15720  ncuts = 0;
15721  cutoff = FALSE;
15722 
15723  /* check all useful linear constraints for feasibility */
15724  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15725  {
15726  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15727  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15728  }
15729 
15730  /* adjust return value */
15731  if( cutoff )
15732  *result = SCIP_CUTOFF;
15733  else if( ncuts > 0 )
15734  *result = SCIP_SEPARATED;
15735 
15736  /* combine linear constraints to get more cuts */
15737  /**@todo further cuts of linear constraints */
15738 
15739  return SCIP_OKAY;
15740 }
15741 
15742 
15743 /** separation method of constraint handler for arbitrary primal solutions */
15744 static
15745 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15746 { /*lint --e{715}*/
15747  SCIP_CONSHDLRDATA* conshdlrdata;
15748  int c;
15749  int depth;
15750  int nrounds;
15751  int maxsepacuts;
15752  int ncuts;
15753  SCIP_Bool cutoff;
15754 
15755  assert(scip != NULL);
15756  assert(conshdlr != NULL);
15757  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15758  assert(result != NULL);
15759 
15760  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15761  assert(conshdlrdata != NULL);
15762  depth = SCIPgetDepth(scip);
15763  nrounds = SCIPgetNSepaRounds(scip);
15764 
15765  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15766 
15767  *result = SCIP_DIDNOTRUN;
15768 
15769  /* only call the separator a given number of times at each node */
15770  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15771  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15772  return SCIP_OKAY;
15773 
15774  /* get the maximal number of cuts allowed in a separation round */
15775  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15776 
15777  *result = SCIP_DIDNOTFIND;
15778  ncuts = 0;
15779  cutoff = FALSE;
15780 
15781  /* check all useful linear constraints for feasibility */
15782  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15783  {
15784  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15785  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15786  }
15787 
15788  /* adjust return value */
15789  if( cutoff )
15790  *result = SCIP_CUTOFF;
15791  else if( ncuts > 0 )
15792  *result = SCIP_SEPARATED;
15793 
15794  /* combine linear constraints to get more cuts */
15795  /**@todo further cuts of linear constraints */
15796 
15797  return SCIP_OKAY;
15798 }
15799 
15800 
15801 /** constraint enforcing method of constraint handler for LP solutions */
15802 static
15803 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15804 { /*lint --e{715}*/
15805  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15806 
15807  return SCIP_OKAY;
15808 }
15809 
15810 /** constraint enforcing method of constraint handler for relaxation solutions */
15811 static
15812 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15813 { /*lint --e{715}*/
15814  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15815 
15816  return SCIP_OKAY;
15817 }
15818 
15819 /** constraint enforcing method of constraint handler for pseudo solutions */
15820 static
15821 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15822 { /*lint --e{715}*/
15823  SCIP_CONSHDLRDATA* conshdlrdata;
15824  SCIP_Bool checkrelmaxabs;
15825  SCIP_Bool violated;
15826  int c;
15827 
15828  assert(scip != NULL);
15829  assert(conshdlr != NULL);
15830  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15831  assert(result != NULL);
15832 
15833  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15834  assert(conshdlrdata != NULL);
15835 
15836  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15837 
15838  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15839 
15840  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
15841  if( objinfeasible )
15842  {
15843  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
15844 
15845  *result = SCIP_DIDNOTRUN;
15846  return SCIP_OKAY;
15847  }
15848 
15849  /* check all linear constraints for feasibility */
15850  violated = FALSE;
15851  for( c = 0; c < nconss && !violated; ++c )
15852  {
15853  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
15854  }
15855 
15856  if( violated )
15857  *result = SCIP_INFEASIBLE;
15858  else
15859  *result = SCIP_FEASIBLE;
15860 
15861  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15862 
15863  return SCIP_OKAY;
15864 }
15865 
15866 
15867 /** feasibility check method of constraint handler for integral solutions */
15868 static
15869 SCIP_DECL_CONSCHECK(consCheckLinear)
15870 { /*lint --e{715}*/
15871  SCIP_CONSHDLRDATA* conshdlrdata;
15872  SCIP_Bool checkrelmaxabs;
15873  int c;
15874 
15875  assert(scip != NULL);
15876  assert(conshdlr != NULL);
15877  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15878  assert(result != NULL);
15879 
15880  *result = SCIP_FEASIBLE;
15881 
15882  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15883  assert(conshdlrdata != NULL);
15884 
15885  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15887  /*debugMsg(scip, "Check method of linear constraints\n");*/
15888 
15889  /* check all linear constraints for feasibility */
15890  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
15891  {
15892  SCIP_Bool violated = FALSE;
15893  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
15894 
15895  if( violated )
15896  {
15897  *result = SCIP_INFEASIBLE;
15898 
15899  if( printreason )
15900  {
15901  SCIP_CONSDATA* consdata;
15902  SCIP_Real activity;
15903 
15904  consdata = SCIPconsGetData(conss[c]);
15905  assert( consdata != NULL);
15906 
15907  activity = consdataGetActivity(scip, consdata, sol);
15908 
15909  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
15910  SCIPinfoMessage(scip, NULL, ";\n");
15911 
15912  if( activity == SCIP_INVALID ) /*lint !e777*/
15913  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
15914  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
15915  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
15916  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
15917  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
15918  }
15919  }
15920  }
15921 
15922  return SCIP_OKAY;
15923 }
15924 
15925 
15926 /** domain propagation method of constraint handler */
15927 static
15928 SCIP_DECL_CONSPROP(consPropLinear)
15929 { /*lint --e{715}*/
15930  SCIP_CONSHDLRDATA* conshdlrdata;
15931  SCIP_Bool rangedrowpropagation = FALSE;
15932  SCIP_Bool tightenbounds;
15933  SCIP_Bool cutoff;
15934 
15935  int nchgbds;
15936  int i;
15937 
15938  assert(scip != NULL);
15939  assert(conshdlr != NULL);
15940  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15941  assert(result != NULL);
15942 
15943  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15944  assert(conshdlrdata != NULL);
15946  /*debugMsg(scip, "Prop method of linear constraints\n");*/
15947 
15948  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
15949  if( SCIPinProbing(scip) )
15950  tightenbounds = TRUE;
15951  else
15952  {
15953  int depth;
15954  int propfreq;
15955  int tightenboundsfreq;
15956  int rangedrowfreq;
15957 
15958  depth = SCIPgetDepth(scip);
15959  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
15960  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
15961  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
15962  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
15963 
15964  /* check if we want to do ranged row propagation */
15965  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
15966  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
15967  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
15968  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
15969  rangedrowpropagation = rangedrowpropagation && (depth % rangedrowfreq == 0);
15970  }
15971 
15972  cutoff = FALSE;
15973  nchgbds = 0;
15974 
15975  /* process constraints marked for propagation */
15976  for( i = 0; i < nmarkedconss && !cutoff; i++ )
15977  {
15978  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
15979  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
15980  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
15981  }
15982 
15983  /* adjust result code */
15984  if( cutoff )
15985  *result = SCIP_CUTOFF;
15986  else if( nchgbds > 0 )
15987  *result = SCIP_REDUCEDDOM;
15988  else
15989  *result = SCIP_DIDNOTFIND;
15990 
15991  return SCIP_OKAY;
15992 }
15993 
15994 
15995 #define MAXCONSPRESOLROUNDS 10
15996 /** presolving method of constraint handler */
15997 static
15998 SCIP_DECL_CONSPRESOL(consPresolLinear)
15999 { /*lint --e{715}*/
16000  SCIP_CONSHDLRDATA* conshdlrdata;
16001  SCIP_CONS* cons;
16002  SCIP_CONSDATA* consdata;
16003  SCIP_Real minactivity;
16004  SCIP_Real maxactivity;
16005  SCIP_Bool minactisrelax;
16006  SCIP_Bool maxactisrelax;
16007  SCIP_Bool cutoff;
16008  int oldnfixedvars;
16009  int oldnaggrvars;
16010  int oldnchgbds;
16011  int oldndelconss;
16012  int oldnupgdconss;
16013  int oldnchgcoefs;
16014  int oldnchgsides;
16015  int firstchange;
16016  int firstupgradetry;
16017  int c;
16018 
16019  assert(scip != NULL);
16020  assert(conshdlr != NULL);
16021  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16022  assert(result != NULL);
16023 
16024  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16025 
16026  /* remember old preprocessing counters */
16027  cutoff = FALSE;
16028  oldnfixedvars = *nfixedvars;
16029  oldnaggrvars = *naggrvars;
16030  oldnchgbds = *nchgbds;
16031  oldndelconss = *ndelconss;
16032  oldnupgdconss = *nupgdconss;
16033  oldnchgcoefs = *nchgcoefs;
16034  oldnchgsides = *nchgsides;
16035 
16036  /* get constraint handler data */
16037  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16038  assert(conshdlrdata != NULL);
16039 
16040  /* process single constraints */
16041  firstchange = INT_MAX;
16042  firstupgradetry = INT_MAX;
16043  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16044  {
16045  int npresolrounds;
16046  SCIP_Bool infeasible;
16047 
16048  infeasible = FALSE;
16049 
16050  cons = conss[c];
16051  assert(SCIPconsIsActive(cons));
16052  consdata = SCIPconsGetData(cons);
16053  assert(consdata != NULL);
16054 
16055  if( consdata->eventdata == NULL )
16056  {
16057  /* catch bound change events of variables */
16058  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16059  assert(consdata->eventdata != NULL);
16060  }
16061 
16062  /* constraint should not be already presolved in the initial round */
16063  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16064  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16065  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16066  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16067 
16068  /* incorporate fixings and aggregations in constraint */
16069  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16070 
16071  if( infeasible )
16072  {
16073  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16074  cutoff = TRUE;
16075  break;
16076  }
16077 
16078  assert(consdata->removedfixings);
16079 
16080  /* we can only presolve linear constraints, that are not modifiable */
16081  if( SCIPconsIsModifiable(cons) )
16082  continue;
16083 
16084  /* remember the first changed constraint to begin the next aggregation round with */
16085  if( firstchange == INT_MAX && consdata->changed )
16086  firstchange = c;
16087 
16088  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16089  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16090  firstupgradetry = c;
16091 
16092  /* check, if constraint is already preprocessed */
16093  if( consdata->presolved )
16094  continue;
16095 
16096  assert(SCIPconsIsActive(cons));
16097 
16098  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16099  SCIPdebugPrintCons(scip, cons, NULL);
16100 
16101  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16102  * to avoid nearly infinite cycling due to very small bound changes)
16103  */
16104  npresolrounds = 0;
16105  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16106  {
16107  assert(!cutoff);
16108  npresolrounds++;
16109 
16110  /* mark constraint being presolved and propagated */
16111  consdata->presolved = TRUE;
16112  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16113 
16114  /* normalize constraint */
16115  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16116 
16117  if( infeasible )
16118  {
16119  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16120  cutoff = TRUE;
16121  break;
16122  }
16123 
16124  /* tighten left and right hand side due to integrality */
16125  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16126 
16127  if( infeasible )
16128  {
16129  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16130  cutoff = TRUE;
16131  break;
16132  }
16133 
16134  /* check bounds */
16135  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16136  {
16137  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16138  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16139  cutoff = TRUE;
16140  break;
16141  }
16142 
16143  /* tighten variable's bounds */
16144  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16145  if( cutoff )
16146  break;
16147 
16148  /* check for fixed variables */
16149  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16150  if( cutoff )
16151  break;
16152 
16153  /* check constraint for infeasibility and redundancy */
16154  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
16155  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16156  {
16157  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16158  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16159  cutoff = TRUE;
16160  break;
16161  }
16162  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16163  {
16164  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16165  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16166  SCIP_CALL( SCIPdelCons(scip, cons) );
16167  assert(!SCIPconsIsActive(cons));
16168 
16169  if( !consdata->upgraded )
16170  (*ndelconss)++;
16171  break;
16172  }
16173  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
16174  {
16175  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16176  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16177  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16178  if( !consdata->upgraded )
16179  (*nchgsides)++;
16180  }
16181  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16182  {
16183  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16184  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16185  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16186  if( !consdata->upgraded )
16187  (*nchgsides)++;
16188  }
16189  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
16190 
16191  /* handle empty constraint */
16192  if( consdata->nvars == 0 )
16193  {
16194  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16195  {
16196  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16197  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16198  cutoff = TRUE;
16199  }
16200  else
16201  {
16202  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16203  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16204  SCIP_CALL( SCIPdelCons(scip, cons) );
16205  assert(!SCIPconsIsActive(cons));
16206 
16207  if( !consdata->upgraded )
16208  (*ndelconss)++;
16209  }
16210  break;
16211  }
16212 
16213  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16214  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16215 
16216  /* try to simplify inequalities */
16217  if( conshdlrdata->simplifyinequalities )
16218  {
16219  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16220 
16221  if( cutoff )
16222  break;
16223  }
16224 
16225  /* aggregation variable in equations */
16226  if( conshdlrdata->aggregatevariables )
16227  {
16228  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16229  if( cutoff )
16230  break;
16231  }
16232  }
16233 
16234  if( !cutoff && !SCIPisStopped(scip) )
16235  {
16236  /* perform ranged row propagation */
16237  if( conshdlrdata->rangedrowpropagation )
16238  {
16239  int lastnfixedvars;
16240 
16241  lastnfixedvars = *nfixedvars;
16242 
16243  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16244  if( !cutoff )
16245  {
16246  if( lastnfixedvars < *nfixedvars )
16247  {
16248  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16249  }
16250  }
16251  }
16252 
16253  /* extract cliques from constraint */
16254  if( !cutoff && SCIPconsIsActive(cons) )
16255  {
16256  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16257  nfixedvars, nchgbds, &cutoff) );
16258 
16259  /* check if the constraint got redundant or infeasible */
16260  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16261  {
16262  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16263  {
16264  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16265  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16266  cutoff = TRUE;
16267  }
16268  else
16269  {
16270  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16271  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16272  SCIP_CALL( SCIPdelCons(scip, cons) );
16273  assert(!SCIPconsIsActive(cons));
16274 
16275  if( !consdata->upgraded )
16276  (*ndelconss)++;
16277  }
16278  }
16279  }
16280 
16281  /* convert special equalities */
16282  if( !cutoff && SCIPconsIsActive(cons) )
16283  {
16284  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16285  }
16286 
16287  /* apply dual presolving for variables that appear in only one constraint */
16288  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
16289  {
16290  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16291  }
16292 
16293  /* check if an inequality is parallel to the objective function */
16294  if( !cutoff && SCIPconsIsActive(cons) )
16295  {
16296  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16297  }
16298 
16299  /* remember the first changed constraint to begin the next aggregation round with */
16300  if( firstchange == INT_MAX && consdata->changed )
16301  firstchange = c;
16302 
16303  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16304  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16305  firstupgradetry = c;
16306  }
16307 
16308  /* singleton column stuffing */
16309  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16310  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowDualReds(scip) )
16311  {
16312  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16313  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16314 
16315  /* handle empty constraint */
16316  if( consdata->nvars == 0 )
16317  {
16318  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16319  {
16320  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16321  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16322  cutoff = TRUE;
16323  }
16324  else
16325  {
16326  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16327  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16328  SCIP_CALL( SCIPdelCons(scip, cons) );
16329  assert(!SCIPconsIsActive(cons));
16330 
16331  if( !consdata->upgraded )
16332  (*ndelconss)++;
16333  }
16334  break;
16335  }
16336  }
16337  }
16338 
16339  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16340  * only apply this expensive procedure in exhaustive presolving timing
16341  */
16342  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16343  {
16344  assert(firstchange >= 0);
16345 
16346  if( firstchange < nconss && conshdlrdata->presolusehashing )
16347  {
16348  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16349  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16350  ndelconss, nchgsides) );
16351  }
16352 
16353  if( firstchange < nconss && conshdlrdata->presolpairwise )
16354  {
16355  SCIP_CONS** usefulconss;
16356  int nusefulconss;
16357  int firstchangenew;
16358  SCIP_Longint npaircomparisons;
16359 
16360  npaircomparisons = 0;
16361  oldndelconss = *ndelconss;
16362  oldnchgsides = *nchgsides;
16363  oldnchgcoefs = *nchgcoefs;
16364 
16365  /* allocate temporary memory */
16366  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16367 
16368  nusefulconss = 0;
16369  firstchangenew = -1;
16370  for( c = 0; c < nconss; ++c )
16371  {
16372  /* update firstchange */
16373  if( c == firstchange )
16374  firstchangenew = nusefulconss;
16375 
16376  /* ignore inactive and modifiable constraints */
16377  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16378  continue;
16379 
16380  usefulconss[nusefulconss] = conss[c];
16381  ++nusefulconss;
16382  }
16383  firstchange = firstchangenew;
16384  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16385 
16386  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16387  {
16388  /* constraint has become inactive or modifiable during pairwise presolving */
16389  if( usefulconss[c] == NULL )
16390  continue;
16391 
16392  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16393 
16394  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16395  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16396  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16397 
16398  if( npaircomparisons > conshdlrdata->nmincomparisons )
16399  {
16400  assert(npaircomparisons > 0);
16401  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16402  break;
16403  oldndelconss = *ndelconss;
16404  oldnchgsides = *nchgsides;
16405  oldnchgcoefs = *nchgcoefs;
16406  npaircomparisons = 0;
16407  }
16408  }
16409  /* free temporary memory */
16410  SCIPfreeBufferArray(scip, &usefulconss);
16411  }
16412  }
16413 
16414  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16415  * in linear constraints and we therefore have full information about it
16416  */
16417  if( !cutoff && firstupgradetry < nconss
16418  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16419  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16420  )
16421  {
16422  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) && !SCIPisStopped(scip) )
16423  {
16424  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16425  }
16426  }
16427 
16428  /* try to upgrade constraints into a more specific constraint type;
16429  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16430  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16431  */
16432  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16433  {
16434  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16435  {
16436  cons = conss[c];
16437 
16438  /* don't upgrade modifiable constraints */
16439  if( SCIPconsIsModifiable(cons) )
16440  continue;
16441 
16442  consdata = SCIPconsGetData(cons);
16443  assert(consdata != NULL);
16444 
16445  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16446  if( consdata->upgradetried )
16447  continue;
16448  /* @todo force that upgrade will be performed later? */
16449  if( !consdata->presolved )
16450  continue;
16451 
16452  consdata->upgradetried = TRUE;
16453  if( SCIPconsIsActive(cons) )
16454  {
16455  SCIP_CONS* upgdcons;
16456 
16457  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16458  if( upgdcons != NULL )
16459  {
16460  /* add the upgraded constraint to the problem */
16461  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16462  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16463  (*nupgdconss)++;
16464 
16465  /* mark the linear constraint being upgraded and to be removed after presolving;
16466  * don't delete it directly, because it may help to preprocess other linear constraints
16467  */
16468  assert(!consdata->upgraded);
16469  consdata->upgraded = TRUE;
16470 
16471  /* delete upgraded inequalities immediately;
16472  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16473  */
16474  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16475  || !conshdlrdata->presolpairwise
16476  || (conshdlrdata->maxaggrnormscale == 0.0) )
16477  {
16478  SCIP_CALL( SCIPdelCons(scip, cons) );
16479  }
16480  }
16481  }
16482  }
16483  }
16484 
16485  /* return the correct result code */
16486  if( cutoff )
16487  *result = SCIP_CUTOFF;
16488  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16489  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16490  *result = SCIP_SUCCESS;
16491  else
16492  *result = SCIP_DIDNOTFIND;
16493 
16494  return SCIP_OKAY;
16495 }
16496 
16497 
16498 /** propagation conflict resolving method of constraint handler */
16499 static
16500 SCIP_DECL_CONSRESPROP(consRespropLinear)
16501 { /*lint --e{715}*/
16502  assert(scip != NULL);
16503  assert(cons != NULL);
16504  assert(result != NULL);
16505 
16506  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16507 
16508  return SCIP_OKAY;
16509 }
16510 
16511 
16512 /** variable rounding lock method of constraint handler */
16513 static
16514 SCIP_DECL_CONSLOCK(consLockLinear)
16515 { /*lint --e{715}*/
16516  SCIP_CONSDATA* consdata;
16517  SCIP_Bool haslhs;
16518  SCIP_Bool hasrhs;
16519  int i;
16520 
16521  assert(scip != NULL);
16522  assert(cons != NULL);
16523  consdata = SCIPconsGetData(cons);
16524  assert(consdata != NULL);
16525 
16526  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16527  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16528 
16529  /* update rounding locks of every single variable */
16530  for( i = 0; i < consdata->nvars; ++i )
16531  {
16532  if( SCIPisPositive(scip, consdata->vals[i]) )
16533  {
16534  if( haslhs )
16535  {
16536  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16537  }
16538  if( hasrhs )
16539  {
16540  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16541  }
16542  }
16543  else
16544  {
16545  if( haslhs )
16546  {
16547  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16548  }
16549  if( hasrhs )
16550  {
16551  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16552  }
16553  }
16554  }
16555 
16556  return SCIP_OKAY;
16557 }
16558 
16559 
16560 /** variable deletion method of constraint handler */
16561 static
16562 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16563 {
16564  assert(scip != NULL);
16565  assert(conshdlr != NULL);
16566  assert(conss != NULL || nconss == 0);
16567 
16568  if( nconss > 0 )
16569  {
16570  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16571  }
16572 
16573  return SCIP_OKAY;
16574 }
16575 
16576 /** constraint display method of constraint handler */
16577 static
16578 SCIP_DECL_CONSPRINT(consPrintLinear)
16579 { /*lint --e{715}*/
16580  assert(scip != NULL);
16581  assert(conshdlr != NULL);
16582  assert(cons != NULL);
16583 
16584  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16585 
16586  return SCIP_OKAY;
16587 }
16588 
16589 /** constraint copying method of constraint handler */
16590 static
16591 SCIP_DECL_CONSCOPY(consCopyLinear)
16592 { /*lint --e{715}*/
16593  SCIP_VAR** sourcevars;
16594  SCIP_Real* sourcecoefs;
16595  const char* consname;
16596  int nvars;
16597 
16598  assert(scip != NULL);
16599  assert(sourcescip != NULL);
16600  assert(sourcecons != NULL);
16601 
16602  /* get variables and coefficients of the source constraint */
16603  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16604  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16605  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16606 
16607  if( name != NULL )
16608  consname = name;
16609  else
16610  consname = SCIPconsGetName(sourcecons);
16611 
16612  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16613  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16614  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16615  assert(cons != NULL || *valid == FALSE);
16616 
16617  /* @todo should also the checkabsolute flag of the constraint be copied? */
16618 
16619  return SCIP_OKAY;
16620 }
16621 
16622 /* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
16623  * except for ranged rows for which exactly two operators '<=' must be present
16624  */
16625 static
16627  const char* str, /**< null terminated input string */
16628  char** firstoperator, /**< pointer to store the string starting at the first operator */
16629  char** secondoperator, /**< pointer to store the string starting at the second operator */
16630  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16631  )
16632 {
16633  char* curr;
16634 
16635  assert(str != NULL);
16636  assert(firstoperator != NULL);
16637  assert(secondoperator != NULL);
16638 
16639  *firstoperator = NULL;
16640  *secondoperator = NULL;
16641 
16642  curr = (char*)str;
16643  *success = TRUE;
16644 
16645  /* loop over the input string to find all operators */
16646  while( *curr && *success )
16647  {
16648  SCIP_Bool found = FALSE;
16649  int increment = 1;
16650 
16651  /* try if we found a possible operator */
16652  switch( *curr )
16653  {
16654  case '<':
16655  case '=':
16656  case '>':
16657 
16658  /* check if the two characters curr[0,1] form an operator together */
16659  if( curr[1] == '=' )
16660  {
16661  found = TRUE;
16662 
16663  /* update increment to continue after this operator */
16664  increment = 2;
16665  }
16666  break;
16667  case '[':
16668  if( strncmp(curr, "[free]", 6) == 0 )
16669  {
16670  found = TRUE;
16671 
16672  /* update increment to continue after this operator */
16673  increment = 6;
16674  }
16675  break;
16676  default:
16677  break;
16678  }
16679 
16680  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16681  if( found )
16682  {
16683  if( *firstoperator == NULL )
16684  {
16685  *firstoperator = curr;
16686  }
16687  else
16688  {
16689  if( *secondoperator != NULL )
16690  {
16691  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16692  *success = FALSE;
16693  }
16694  else if( strncmp(*firstoperator, "<=", 2) != 0 )
16695  {
16696  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16697  *success = FALSE;
16698  }
16699  else if( strncmp(curr, "<=", 2) != 0 )
16700  {
16701  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16702  *success = FALSE;
16703  }
16704 
16705  *secondoperator = curr;
16706  }
16707  }
16708 
16709  curr += increment;
16710  }
16711 
16712  /* check if we did find at least one operator */
16713  if( *success )
16714  {
16715  if( *firstoperator == NULL )
16716  {
16717  SCIPerrorMessage("Could not find any operator in line %s\n", str);
16718  *success = FALSE;
16719  }
16720  }
16721 
16722  return SCIP_OKAY;
16723 }
16724 
16725 /** constraint parsing method of constraint handler */
16726 static
16727 SCIP_DECL_CONSPARSE(consParseLinear)
16728 { /*lint --e{715}*/
16729  SCIP_VAR** vars;
16730  SCIP_Real* coefs;
16731  int nvars;
16732  int coefssize;
16733  int requsize;
16734  SCIP_Real lhs;
16735  SCIP_Real rhs;
16736  char* endptr;
16737  char* firstop;
16738  char* secondop;
16739  SCIP_Bool operatorsuccess;
16740  char* lhsstrptr;
16741  char* rhsstrptr;
16742  char* varstrptr;
16743 
16744  assert(scip != NULL);
16745  assert(success != NULL);
16746  assert(str != NULL);
16747  assert(name != NULL);
16748  assert(cons != NULL);
16749 
16750  /* set left and right hand side to their default values */
16751  lhs = -SCIPinfinity(scip);
16752  rhs = SCIPinfinity(scip);
16753 
16754  (*success) = FALSE;
16755 
16756  /* return of string empty */
16757  if( !*str )
16758  return SCIP_OKAY;
16759 
16760  /* ignore whitespace */
16761  while( isspace((unsigned char)*str) )
16762  ++str;
16763 
16764  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16765  * and the special word [free]
16766  */
16767  SCIP_CALL( findOperators(str, &firstop, &secondop, &operatorsuccess) );
16768 
16769  /* if the grammar is not valid for parsing a linear constraint, return */
16770  if( ! operatorsuccess )
16771  return SCIP_OKAY;
16772 
16773  varstrptr = (char *)str;
16774  lhsstrptr = rhsstrptr = NULL;
16775  assert(firstop != NULL);
16776 
16777  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16778  switch( *firstop )
16779  {
16780  case '<':
16781  assert(firstop[1] == '=');
16782  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16783  if( secondop != NULL )
16784  {
16785  assert(secondop[0] == '<' && secondop[1] == '=');
16786  lhsstrptr = (char *)str;
16787  varstrptr = firstop + 2;
16788  rhsstrptr = secondop + 2;
16789  }
16790  else
16791  {
16792  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16793  lhsstrptr = NULL;
16794  varstrptr = (char *)str;
16795  rhsstrptr = firstop + 2;
16796  }
16797  break;
16798  case '>':
16799  assert(firstop[1] == '=');
16800  assert(secondop == NULL);
16801  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16802  lhsstrptr = firstop + 2;
16803  break;
16804  case '=':
16805  assert(firstop[1] == '=');
16806  assert(secondop == NULL);
16807  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16808  rhsstrptr = firstop + 2;
16809  lhsstrptr = firstop + 2;
16810  break;
16811  case '[':
16812  assert(strncmp(firstop, "[free]", 6) == 0);
16813  assert(secondop == NULL);
16814  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16815  break;
16816  default:
16817  /* it should not be possible that a different character appears in that position */
16818  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16819  return SCIP_READERROR;
16820  }
16821 
16822  /* parse left hand side, if necessary */
16823  if( lhsstrptr != NULL )
16824  {
16825  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16826  {
16827  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16828  return SCIP_OKAY;
16829  }
16830 
16831  /* in case of an equation, assign the left also to the right hand side */
16832  if( rhsstrptr == lhsstrptr )
16833  rhs = lhs;
16834  }
16835 
16836  /* parse right hand side, if different from left hand side */
16837  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
16838  {
16839  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
16840  {
16841  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
16842  return SCIP_OKAY;
16843  }
16844  }
16845 
16846  /* initialize buffers for storing the variables and coefficients */
16847  coefssize = 100;
16848  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
16849  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
16850 
16851  assert(varstrptr != NULL);
16852 
16853  /* parse linear sum to get variables and coefficients */
16854  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16855 
16856  if( *success && requsize > coefssize )
16857  {
16858  /* realloc buffers and try again */
16859  coefssize = requsize;
16860  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
16861  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
16862 
16863  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16864  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
16865  }
16866 
16867  if( !*success )
16868  {
16869  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
16870  }
16871  else
16872  {
16873  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
16874  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
16875  }
16876 
16877  SCIPfreeBufferArray(scip, &coefs);
16878  SCIPfreeBufferArray(scip, &vars);
16879 
16880  return SCIP_OKAY;
16881 }
16882 
16883 
16884 /** constraint method of constraint handler which returns the variables (if possible) */
16885 static
16886 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
16887 { /*lint --e{715}*/
16888  SCIP_CONSDATA* consdata;
16889 
16890  consdata = SCIPconsGetData(cons);
16891  assert(consdata != NULL);
16892 
16893  if( varssize < consdata->nvars )
16894  (*success) = FALSE;
16895  else
16896  {
16897  assert(vars != NULL);
16898 
16899  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
16900  (*success) = TRUE;
16901  }
16902 
16903  return SCIP_OKAY;
16904 }
16905 
16906 /**! [Callback for the number of variables]*/
16907 /** constraint method of constraint handler which returns the number of variables (if possible) */
16908 static
16909 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
16910 { /*lint --e{715}*/
16911  SCIP_CONSDATA* consdata;
16912 
16913  consdata = SCIPconsGetData(cons);
16914  assert(consdata != NULL);
16915 
16916  (*nvars) = consdata->nvars;
16917  (*success) = TRUE;
16918 
16919  return SCIP_OKAY;
16920 }
16921 /**! [Callback for the number of variables]*/
16922 
16923 /*
16924  * Callback methods of event handler
16925  */
16927 static
16928 SCIP_DECL_EVENTEXEC(eventExecLinear)
16929 { /*lint --e{715}*/
16930  SCIP_CONS* cons;
16931  SCIP_CONSDATA* consdata;
16932  SCIP_VAR* var;
16933  SCIP_EVENTTYPE eventtype;
16934 
16935  assert(scip != NULL);
16936  assert(eventhdlr != NULL);
16937  assert(eventdata != NULL);
16938  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
16939  assert(event != NULL);
16940 
16941  cons = eventdata->cons;
16942  assert(cons != NULL);
16943  consdata = SCIPconsGetData(cons);
16944  assert(consdata != NULL);
16946  /* we can skip events droped for deleted constraints */
16947  if( SCIPconsIsDeleted(cons) )
16948  return SCIP_OKAY;
16949 
16950  eventtype = SCIPeventGetType(event);
16951  var = SCIPeventGetVar(event);
16952 
16953  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
16954  {
16955  SCIP_Real oldbound;
16956  SCIP_Real newbound;
16957  SCIP_Real val;
16958  int varpos;
16959 
16960  varpos = eventdata->varpos;
16961  assert(0 <= varpos && varpos < consdata->nvars);
16962  oldbound = SCIPeventGetOldbound(event);
16963  newbound = SCIPeventGetNewbound(event);
16964  assert(var != NULL);
16965  assert(consdata->vars[varpos] == var);
16966  val = consdata->vals[varpos];
16967 
16968  /* we only need to update the activities if the constraint is active,
16969  * otherwise we mark them to be invalid
16970  */
16971  if( SCIPconsIsActive(cons) )
16972  {
16973  /* update the activity values */
16974  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
16975  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
16976  else
16977  {
16978  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
16979  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
16980  }
16981  }
16982  else
16983  consdataInvalidateActivities(consdata);
16984 
16985  consdata->presolved = FALSE;
16986  consdata->rangedrowpropagated = 0;
16987 
16988  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
16989  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
16990  {
16991  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
16992 
16993  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16994  if( consdata->maxactdeltavar == var )
16995  {
16996  consdata->maxactdelta = SCIP_INVALID;
16997  consdata->maxactdeltavar = NULL;
16998  }
16999 
17000  /* check whether bound tightening might now be successful */
17001  if( consdata->boundstightened > 0)
17002  {
17003  switch( eventtype )
17004  {
17006  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17007  consdata->boundstightened = 0;
17008  break;
17010  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17011  consdata->boundstightened = 0;
17012  break;
17013  default:
17014  SCIPerrorMessage("invalid event type %d\n", eventtype);
17015  return SCIP_INVALIDDATA;
17016  }
17017  }
17018  }
17019  /* update maximal activity delta if a bound was relaxed */
17020  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17021  {
17022  SCIP_Real lb;
17023  SCIP_Real ub;
17024  SCIP_Real domain;
17025  SCIP_Real delta;
17026 
17027  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17028 
17029  lb = SCIPvarGetLbLocal(var);
17030  ub = SCIPvarGetUbLocal(var);
17031 
17032  domain = ub - lb;
17033  delta = REALABS(val) * domain;
17034 
17035  if( delta > consdata->maxactdelta )
17036  {
17037  consdata->maxactdelta = delta;
17038  consdata->maxactdeltavar = var;
17039  }
17040  }
17041  }
17042  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17043  {
17044  /* we want to remove the fixed variable */
17045  consdata->presolved = FALSE;
17046  consdata->removedfixings = FALSE;
17047  consdata->rangedrowpropagated = 0;
17048 
17049  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17050  if( consdata->maxactdeltavar == var )
17051  {
17052  consdata->maxactdelta = SCIP_INVALID;
17053  consdata->maxactdeltavar = NULL;
17054  }
17055  }
17056 
17057  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17058  {
17059  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17060  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17061  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17062  consdata->presolved = FALSE;
17063  }
17064  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17065  {
17066  SCIP_Real oldbound;
17067  SCIP_Real newbound;
17068  SCIP_Real val;
17069  int varpos;
17070 
17071  varpos = eventdata->varpos;
17072  assert(0 <= varpos && varpos < consdata->nvars);
17073  oldbound = SCIPeventGetOldbound(event);
17074  newbound = SCIPeventGetNewbound(event);
17075  assert(var != NULL);
17076  assert(consdata->vars[varpos] == var);
17077  val = consdata->vals[varpos];
17078 
17079  consdata->rangedrowpropagated = 0;
17080 
17081  /* update the activity values */
17082  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17083  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17084  else
17085  {
17086  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17087  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17088  }
17089  }
17090  else
17091  {
17092  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17093  consdata->varsdeleted = TRUE;
17094  }
17095 
17096  return SCIP_OKAY;
17097 }
17098 
17099 
17100 /*
17101  * Callback methods of conflict handler
17102  */
17103 
17104 static
17105 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17106 { /*lint --e{715}*/
17107  SCIP_VAR** vars;
17108  SCIP_Real* vals;
17109  SCIP_Real lhs;
17110  int i;
17111 
17112  assert(scip != NULL);
17113  assert(conflicthdlr != NULL);
17114  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17115  assert(bdchginfos != NULL || nbdchginfos == 0);
17116  assert(result != NULL);
17117 
17118  /* don't process already resolved conflicts */
17119  if( resolved )
17120  {
17121  *result = SCIP_DIDNOTRUN;
17122  return SCIP_OKAY;
17123  }
17124 
17125  *result = SCIP_DIDNOTFIND;
17126 
17127  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17128  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17129  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17130  lhs = 1.0;
17131  for( i = 0; i < nbdchginfos; ++i )
17132  {
17133  assert(bdchginfos != NULL);
17134 
17135  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17136 
17137  /* we can only treat binary variables */
17138  /**@todo extend linear conflict constraints to some non-binary cases */
17139  if( !SCIPvarIsBinary(vars[i]) )
17140  break;
17141 
17142  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17143  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17144  vals[i] = 1.0;
17145  else
17146  {
17147  vals[i] = -1.0;
17148  lhs -= 1.0;
17149  }
17150  }
17151 
17152  if( i == nbdchginfos )
17153  {
17154  SCIP_CONS* cons;
17155  SCIP_CONS* upgdcons;
17156  char consname[SCIP_MAXSTRLEN];
17157 
17158  /* create a constraint out of the conflict set */
17159  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17160  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17161  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17162 
17163  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17164  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17165  if( upgdcons != NULL )
17166  {
17167  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17168  cons = upgdcons;
17169  }
17170 
17171  /* add conflict to SCIP */
17172  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17173 
17174  *result = SCIP_CONSADDED;
17175  }
17176 
17177  /* free temporary memory */
17178  SCIPfreeBufferArray(scip, &vals);
17179  SCIPfreeBufferArray(scip, &vars);
17180 
17181  return SCIP_OKAY;
17182 }
17183 
17184 
17185 /*
17186  * Quadratic constraint upgrading
17187  */
17188 
17189 
17190 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
17191  */
17192 static
17193 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
17194 { /*lint --e{715}*/
17195  SCIP_CONSDATA* upgdconsdata;
17196 
17197  assert(scip != NULL);
17198  assert(cons != NULL);
17199  assert(nupgdconss != NULL);
17200  assert(upgdconss != NULL);
17201 
17202  *nupgdconss = 0;
17203 
17204  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
17205  SCIPdebugPrintCons(scip, cons, NULL);
17206 
17207  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
17208  return SCIP_OKAY;
17209  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
17210  return SCIP_OKAY;
17211 
17212  if( upgdconsssize < 1 )
17213  {
17214  /* signal that we need more memory */
17215  *nupgdconss = -1;
17216  return SCIP_OKAY;
17217  }
17218 
17219  *nupgdconss = 1;
17220  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17221  SCIPgetNLinearVarsQuadratic(scip, cons),
17222  SCIPgetLinearVarsQuadratic(scip, cons),
17223  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
17224  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
17228  SCIPconsIsStickingAtNode(cons)) );
17229 
17230  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17231  assert(upgdconsdata != NULL);
17232 
17233  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original quadratic constraint */
17234  upgdconsdata->checkabsolute = TRUE;
17235 
17236  SCIPdebugMsg(scip, "created linear constraint:\n");
17237  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17238 
17239  return SCIP_OKAY;
17240 }
17241 
17242 /** tries to upgrade a nonlinear constraint into a linear constraint */
17243 static
17244 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17245 {
17246  SCIP_CONSDATA* upgdconsdata;
17247 
17248  assert(nupgdconss != NULL);
17249  assert(upgdconss != NULL);
17250 
17251  *nupgdconss = 0;
17252 
17253  /* no interest in nonlinear constraints */
17254  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
17255  return SCIP_OKAY;
17256 
17257  /* no interest in constant constraints */
17258  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
17259  return SCIP_OKAY;
17260 
17261  if( upgdconsssize < 1 )
17262  {
17263  /* request larger upgdconss array */
17264  *nupgdconss = -1;
17265  return SCIP_OKAY;
17266  }
17267 
17268  *nupgdconss = 1;
17269  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17271  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
17275  SCIPconsIsStickingAtNode(cons)) );
17276 
17277  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17278  assert(upgdconsdata != NULL);
17279 
17280  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17281  upgdconsdata->checkabsolute = TRUE;
17282 
17283  SCIPdebugMsg(scip, "created linear constraint:\n");
17284  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17285 
17286  return SCIP_OKAY;
17287 }
17288 
17289 /*
17290  * constraint specific interface methods
17291  */
17292 
17293 /** creates the handler for linear constraints and includes it in SCIP */
17295  SCIP* scip /**< SCIP data structure */
17296  )
17297 {
17298  SCIP_CONSHDLRDATA* conshdlrdata;
17299  SCIP_CONSHDLR* conshdlr;
17300  SCIP_EVENTHDLR* eventhdlr;
17301  SCIP_CONFLICTHDLR* conflicthdlr;
17302 
17303  assert(scip != NULL);
17304 
17305  /* create event handler for bound change events */
17307  eventExecLinear, NULL) );
17308 
17309  /* create conflict handler for linear constraints */
17311  conflictExecLinear, NULL) );
17312 
17313  /* create constraint handler data */
17314  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17315 
17316  /* include constraint handler */
17319  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17320  conshdlrdata) );
17321 
17322  assert(conshdlr != NULL);
17323 
17324  /* set non-fundamental callbacks via specific setter functions */
17325  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17326  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17327  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17328  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17329  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17330  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17331  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17332  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17333  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17334  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17335  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17336  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17337  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17338  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17339  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17340  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17342  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17343  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17345  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17346  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17347 
17348  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
17349  {
17350  /* include function that upgrades quadratic constraint to linear constraints */
17352  }
17353 
17354  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17355  {
17356  /* include the linear constraint upgrade in the nonlinear constraint handler */
17358  }
17359 
17360  /* add linear constraint handler parameters */
17361  SCIP_CALL( SCIPaddIntParam(scip,
17362  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17363  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17364  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17365  SCIP_CALL( SCIPaddIntParam(scip,
17366  "constraints/" CONSHDLR_NAME "/maxrounds",
17367  "maximal number of separation rounds per node (-1: unlimited)",
17368  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17369  SCIP_CALL( SCIPaddIntParam(scip,
17370  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17371  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17372  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17373  SCIP_CALL( SCIPaddIntParam(scip,
17374  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17375  "maximal number of cuts separated per separation round",
17376  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17377  SCIP_CALL( SCIPaddIntParam(scip,
17378  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17379  "maximal number of cuts separated per separation round in the root node",
17380  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17382  "constraints/" CONSHDLR_NAME "/presolpairwise",
17383  "should pairwise constraint comparison be performed in presolving?",
17384  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17386  "constraints/" CONSHDLR_NAME "/presolusehashing",
17387  "should hash table be used for detecting redundant constraints in advance",
17388  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17389  SCIP_CALL( SCIPaddIntParam(scip,
17390  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17391  "number for minimal pairwise presolve comparisons",
17392  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17394  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17395  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17396  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17398  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17399  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17400  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17402  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17403  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17404  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17406  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17407  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17408  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17410  "constraints/" CONSHDLR_NAME "/separateall",
17411  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17412  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17414  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17415  "should presolving search for aggregations in equations",
17416  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17418  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17419  "should presolving try to simplify inequalities",
17420  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17422  "constraints/" CONSHDLR_NAME "/dualpresolving",
17423  "should dual presolving steps be performed?",
17424  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17426  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17427  "should stuffing of singleton continuous variables be performed?",
17428  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17430  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17431  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17432  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17434  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17435  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17437  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17438  "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)?",
17439  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17441  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17442  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17443  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17445  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17446  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17447  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17449  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17450  "should presolving try to detect subsets of constraints parallel to the objective function?",
17451  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17453  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17454  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17455  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17457  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17458  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17459  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17460  SCIP_CALL( SCIPaddIntParam(scip,
17461  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17462  "maximum depth to apply ranged row propagation",
17463  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17464  SCIP_CALL( SCIPaddIntParam(scip,
17465  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17466  "frequency for applying ranged row propagation",
17467  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17469  "constraints/" CONSHDLR_NAME "/multaggrremove",
17470  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17471  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17472 
17473  return SCIP_OKAY;
17474 }
17475 
17476 /** includes a linear constraint update method into the linear constraint handler */
17478  SCIP* scip, /**< SCIP data structure */
17479  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17480  int priority, /**< priority of upgrading method */
17481  const char* conshdlrname /**< name of the constraint handler */
17482  )
17483 {
17484  SCIP_CONSHDLR* conshdlr;
17485  SCIP_CONSHDLRDATA* conshdlrdata;
17486  SCIP_LINCONSUPGRADE* linconsupgrade;
17487  char paramname[SCIP_MAXSTRLEN];
17488  char paramdesc[SCIP_MAXSTRLEN];
17489 
17490  assert(scip != NULL);
17491  assert(linconsupgd != NULL);
17492  assert(conshdlrname != NULL );
17493 
17494  /* find the linear constraint handler */
17495  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17496  if( conshdlr == NULL )
17497  {
17498  SCIPerrorMessage("linear constraint handler not found\n");
17499  return SCIP_PLUGINNOTFOUND;
17500  }
17501 
17502  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17503  assert(conshdlrdata != NULL);
17504 
17505  /* check if linear constraint update method already exists in constraint handler data */
17506  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17507  {
17508  /* create a linear constraint upgrade data object */
17509  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17510 
17511  /* insert linear constraint update method into constraint handler data */
17512  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17513 
17514  /* adds parameter to turn on and off the upgrading step */
17515  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17516  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17518  paramname, paramdesc,
17519  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17520  }
17521 
17522  return SCIP_OKAY;
17523 }
17524 
17525 /** creates and captures a linear constraint
17526  *
17527  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17528  */
17530  SCIP* scip, /**< SCIP data structure */
17531  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17532  const char* name, /**< name of constraint */
17533  int nvars, /**< number of nonzeros in the constraint */
17534  SCIP_VAR** vars, /**< array with variables of constraint entries */
17535  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17536  SCIP_Real lhs, /**< left hand side of constraint */
17537  SCIP_Real rhs, /**< right hand side of constraint */
17538  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17539  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17540  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17541  * Usually set to TRUE. */
17542  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17543  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17544  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17545  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17546  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17547  * Usually set to TRUE. */
17548  SCIP_Bool local, /**< is constraint only valid locally?
17549  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17550  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17551  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17552  * adds coefficients to this constraint. */
17553  SCIP_Bool dynamic, /**< is constraint subject to aging?
17554  * Usually set to FALSE. Set to TRUE for own cuts which
17555  * are separated as constraints. */
17556  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17557  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17558  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17559  * if it may be moved to a more global node?
17560  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17561  )
17562 {
17563  SCIP_CONSHDLR* conshdlr;
17564  SCIP_CONSDATA* consdata;
17565 
17566  assert(scip != NULL);
17567  assert(cons != NULL);
17568 
17569  /* find the linear constraint handler */
17570  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17571  if( conshdlr == NULL )
17572  {
17573  SCIPerrorMessage("linear constraint handler not found\n");
17574  return SCIP_PLUGINNOTFOUND;
17575  }
17576 
17577  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17578  * constraint after presolving we have to ensure that it holds active variables
17579  */
17580  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17581  {
17582  SCIP_VAR** consvars;
17583  SCIP_Real* consvals;
17584  SCIP_Real constant = 0.0;
17585  int nconsvars;
17586  int requiredsize;
17587 
17588  nconsvars = nvars;
17589  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17590  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17591 
17592  /* get active variables for new constraint */
17593  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17594 
17595  /* if space was not enough we need to resize the buffers */
17596  if( requiredsize > nconsvars )
17597  {
17598  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17599  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17600 
17601  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17602  assert(requiredsize <= nconsvars);
17603  }
17604 
17605  /* adjust sides and check that we do not subtract infinity values */
17606  if( SCIPisInfinity(scip, REALABS(constant)) )
17607  {
17608  if( constant < 0.0 )
17609  {
17610  if( SCIPisInfinity(scip, lhs) )
17611  {
17612  SCIPfreeBufferArray(scip, &consvals);
17613  SCIPfreeBufferArray(scip, &consvars);
17614 
17615  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);
17616 
17617  SCIPABORT();
17618  return SCIP_INVALIDDATA; /*lint !e527*/
17619  }
17620  if( SCIPisInfinity(scip, rhs) )
17621  {
17622  SCIPfreeBufferArray(scip, &consvals);
17623  SCIPfreeBufferArray(scip, &consvars);
17624 
17625  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);
17626 
17627  SCIPABORT();
17628  return SCIP_INVALIDDATA; /*lint !e527*/
17629  }
17630 
17631  lhs = -SCIPinfinity(scip);
17632  rhs = -SCIPinfinity(scip);
17633  }
17634  else
17635  {
17636  if( SCIPisInfinity(scip, -lhs) )
17637  {
17638  SCIPfreeBufferArray(scip, &consvals);
17639  SCIPfreeBufferArray(scip, &consvars);
17640 
17641  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);
17642 
17643  SCIPABORT();
17644  return SCIP_INVALIDDATA; /*lint !e527*/
17645  }
17646  if( SCIPisInfinity(scip, -rhs) )
17647  {
17648  SCIPfreeBufferArray(scip, &consvals);
17649  SCIPfreeBufferArray(scip, &consvars);
17650 
17651  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);
17652 
17653  SCIPABORT();
17654  return SCIP_INVALIDDATA; /*lint !e527*/
17655  }
17656 
17657  lhs = SCIPinfinity(scip);
17658  rhs = SCIPinfinity(scip);
17659  }
17660  }
17661  else
17662  {
17663  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17664  lhs -= constant;
17665  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17666  rhs -= constant;
17667 
17668  if( SCIPisInfinity(scip, -lhs) )
17669  lhs = -SCIPinfinity(scip);
17670  else if( SCIPisInfinity(scip, lhs) )
17671  lhs = SCIPinfinity(scip);
17672 
17673  if( SCIPisInfinity(scip, rhs) )
17674  rhs = SCIPinfinity(scip);
17675  else if( SCIPisInfinity(scip, -rhs) )
17676  rhs = -SCIPinfinity(scip);
17677  }
17678 
17679  /* create constraint data */
17680  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17681  assert(consdata != NULL);
17682 
17683  SCIPfreeBufferArray(scip, &consvals);
17684  SCIPfreeBufferArray(scip, &consvars);
17685  }
17686  else
17687  {
17688  /* create constraint data */
17689  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17690  assert(consdata != NULL);
17691  }
17692 
17693  /* create constraint */
17694  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17695  local, modifiable, dynamic, removable, stickingatnode) );
17696 
17697  return SCIP_OKAY;
17698 }
17699 
17700 /** creates and captures a linear constraint
17701  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17702  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17703  *
17704  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17705  *
17706  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17707  */
17709  SCIP* scip, /**< SCIP data structure */
17710  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17711  const char* name, /**< name of constraint */
17712  int nvars, /**< number of nonzeros in the constraint */
17713  SCIP_VAR** vars, /**< array with variables of constraint entries */
17714  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17715  SCIP_Real lhs, /**< left hand side of constraint */
17716  SCIP_Real rhs /**< right hand side of constraint */
17717  )
17718 {
17719  assert(scip != NULL);
17720 
17721  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17722  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17723 
17724  return SCIP_OKAY;
17726 
17727 /** creates by copying and captures a linear constraint */
17729  SCIP* scip, /**< target SCIP data structure */
17730  SCIP_CONS** cons, /**< pointer to store the created target constraint */
17731  SCIP* sourcescip, /**< source SCIP data structure */
17732  const char* name, /**< name of constraint */
17733  int nvars, /**< number of variables in source variable array */
17734  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17735  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17736  SCIP_Real lhs, /**< left hand side of the linear constraint */
17737  SCIP_Real rhs, /**< right hand side of the linear constraint */
17738  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17739  * variables of the target SCIP */
17740  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17741  * target constraints */
17742  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17743  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17744  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17745  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17746  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17747  SCIP_Bool local, /**< is constraint only valid locally? */
17748  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17749  SCIP_Bool dynamic, /**< is constraint subject to aging? */
17750  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17751  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17752  * if it may be moved to a more global node? */
17753  SCIP_Bool global, /**< create a global or a local copy? */
17754  SCIP_Bool* valid /**< pointer to store if the copying was valid */
17755  )
17756 {
17757  SCIP_VAR** vars;
17758  SCIP_Real* coefs;
17759 
17760  SCIP_Real constant;
17761  int requiredsize;
17762  int v;
17763  SCIP_Bool success;
17764 
17765  if( SCIPisGT(scip, lhs, rhs) )
17766  {
17767  *valid = FALSE;
17768  return SCIP_OKAY;
17769  }
17770 
17771  (*valid) = TRUE;
17772 
17773  if( nvars == 0 )
17774  {
17775  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17776  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17777  return SCIP_OKAY;
17778  }
17779 
17780  /* duplicate variable array */
17781  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17782 
17783  /* duplicate coefficient array */
17784  if( sourcecoefs != NULL )
17785  {
17786  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17787  }
17788  else
17789  {
17790  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
17791  for( v = 0; v < nvars; ++v )
17792  coefs[v] = 1.0;
17793  }
17794 
17795  constant = 0.0;
17796 
17797  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17798  * the target SCIP
17799  */
17800  if( !SCIPvarIsOriginal(vars[0]) )
17801  {
17802  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
17803 
17804  if( requiredsize > nvars )
17805  {
17806  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
17807  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
17808 
17809  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
17810  assert(requiredsize <= nvars);
17811  }
17812  }
17813  else
17814  {
17815  for( v = 0; v < nvars; ++v )
17816  {
17817  assert(SCIPvarIsOriginal(vars[v]));
17818  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
17819  assert(vars[v] != NULL);
17820  }
17821  }
17822 
17823  success = TRUE;
17824  /* map variables of the source constraint to variables of the target SCIP */
17825  for( v = 0; v < nvars && success; ++v )
17826  {
17827  SCIP_VAR* var;
17828  var = vars[v];
17829 
17830  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
17831  assert(!(success) || vars[v] != NULL);
17832  }
17833 
17834  /* only create the target constraint, if all variables could be copied */
17835  if( success )
17836  {
17837  if( !SCIPisInfinity(scip, -lhs) )
17838  lhs -= constant;
17839 
17840  if( !SCIPisInfinity(scip, rhs) )
17841  rhs -= constant;
17842 
17843  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17844  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17845  }
17846  else
17847  *valid = FALSE;
17848 
17849  /* free buffer array */
17850  SCIPfreeBufferArray(scip, &coefs);
17851  SCIPfreeBufferArray(scip, &vars);
17852 
17853  return SCIP_OKAY;
17854 }
17855 
17856 /** adds coefficient to linear constraint (if it is not zero) */
17858  SCIP* scip, /**< SCIP data structure */
17859  SCIP_CONS* cons, /**< constraint data */
17860  SCIP_VAR* var, /**< variable of constraint entry */
17861  SCIP_Real val /**< coefficient of constraint entry */
17862  )
17863 {
17864  assert(scip != NULL);
17865  assert(cons != NULL);
17866  assert(var != NULL);
17867 
17868  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17869  {
17870  SCIPerrorMessage("constraint is not linear\n");
17871  return SCIP_INVALIDDATA;
17872  }
17873 
17874  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17875  * constraint after presolving we have to ensure that it holds active variables
17876  */
17877  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
17878  {
17879  SCIP_CONSDATA* consdata;
17880  SCIP_VAR** consvars;
17881  SCIP_Real* consvals;
17882  SCIP_Real constant = 0.0;
17883  SCIP_Real rhs;
17884  SCIP_Real lhs;
17885  int nconsvars;
17886  int requiredsize;
17887  int v;
17888 
17889  nconsvars = 1;
17890  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
17891  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
17892  consvars[0] = var;
17893  consvals[0] = val;
17894 
17895  /* get active variables for new constraint */
17896  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17897 
17898  /* if space was not enough we need to resize the buffers */
17899  if( requiredsize > nconsvars )
17900  {
17901  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17902  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17903 
17904  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17905  assert(requiredsize <= nconsvars);
17906  }
17907 
17908  consdata = SCIPconsGetData(cons);
17909  assert(consdata != NULL);
17910 
17911  lhs = consdata->lhs;
17912  rhs = consdata->rhs;
17913 
17914  /* adjust sides and check that we do not subtract infinity values */
17915  /* constant is infinite */
17916  if( SCIPisInfinity(scip, REALABS(constant)) )
17917  {
17918  if( constant < 0.0 )
17919  {
17920  if( SCIPisInfinity(scip, lhs) )
17921  {
17922  SCIPfreeBufferArray(scip, &consvals);
17923  SCIPfreeBufferArray(scip, &consvars);
17924 
17925  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));
17926 
17927  SCIPABORT();
17928  return SCIP_INVALIDDATA; /*lint !e527*/
17929  }
17930  if( SCIPisInfinity(scip, rhs) )
17931  {
17932  SCIPfreeBufferArray(scip, &consvals);
17933  SCIPfreeBufferArray(scip, &consvars);
17934 
17935  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));
17936 
17937  SCIPABORT();
17938  return SCIP_INVALIDDATA; /*lint !e527*/
17939  }
17940 
17941  lhs = -SCIPinfinity(scip);
17942  rhs = -SCIPinfinity(scip);
17943  }
17944  else
17945  {
17946  if( SCIPisInfinity(scip, -lhs) )
17947  {
17948  SCIPfreeBufferArray(scip, &consvals);
17949  SCIPfreeBufferArray(scip, &consvars);
17950 
17951  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));
17952 
17953  SCIPABORT();
17954  return SCIP_INVALIDDATA; /*lint !e527*/
17955  }
17956  if( SCIPisInfinity(scip, -rhs) )
17957  {
17958  SCIPfreeBufferArray(scip, &consvals);
17959  SCIPfreeBufferArray(scip, &consvars);
17960 
17961  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));
17962 
17963  SCIPABORT();
17964  return SCIP_INVALIDDATA; /*lint !e527*/
17965  }
17966 
17967  lhs = SCIPinfinity(scip);
17968  rhs = SCIPinfinity(scip);
17969  }
17970  }
17971  /* constant is not infinite */
17972  else
17973  {
17974  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17975  lhs -= constant;
17976  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17977  rhs -= constant;
17978 
17979  if( SCIPisInfinity(scip, -lhs) )
17980  lhs = -SCIPinfinity(scip);
17981  else if( SCIPisInfinity(scip, lhs) )
17982  lhs = SCIPinfinity(scip);
17983 
17984  if( SCIPisInfinity(scip, rhs) )
17985  rhs = SCIPinfinity(scip);
17986  else if( SCIPisInfinity(scip, -rhs) )
17987  rhs = -SCIPinfinity(scip);
17988  }
17989 
17990  /* add all active variables to constraint */
17991  for( v = nconsvars - 1; v >= 0; --v )
17992  {
17993  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
17994  }
17995 
17996  /* update left and right hand sides */
17997  SCIP_CALL( chgLhs(scip, cons, lhs));
17998  SCIP_CALL( chgRhs(scip, cons, rhs));
17999 
18000  SCIPfreeBufferArray(scip, &consvals);
18001  SCIPfreeBufferArray(scip, &consvars);
18002  }
18003  else
18004  {
18005  SCIP_CALL( addCoef(scip, cons, var, val) );
18006  }
18007 
18008  return SCIP_OKAY;
18009 }
18010 
18011 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18012  * not yet contained in the constraint
18013  *
18014  * @note This method may only be called during problem creation stage for an original constraint and variable.
18015  *
18016  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18017  */
18019  SCIP* scip, /**< SCIP data structure */
18020  SCIP_CONS* cons, /**< constraint data */
18021  SCIP_VAR* var, /**< variable of constraint entry */
18022  SCIP_Real val /**< new coefficient of constraint entry */
18023  )
18024 {
18025  SCIP_CONSDATA* consdata;
18026  SCIP_VAR** vars;
18027  SCIP_Bool found;
18028  int i;
18029 
18030  assert(scip != NULL);
18031  assert(cons != NULL);
18032  assert(var != NULL);
18033 
18034  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18035  {
18036  SCIPerrorMessage("constraint is not linear\n");
18037  return SCIP_INVALIDDATA;
18038  }
18039 
18040  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18041  {
18042  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18043  return SCIP_INVALIDDATA;
18044  }
18045 
18046  consdata = SCIPconsGetData(cons);
18047  assert(consdata != NULL);
18048 
18049  vars = consdata->vars;
18050  found = FALSE;
18051  i = 0;
18052  while( i < consdata->nvars )
18053  {
18054  if( vars[i] == var )
18055  {
18056  if( found || SCIPisZero(scip, val) )
18057  {
18058  SCIP_CALL( delCoefPos(scip, cons, i) );
18059 
18060  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18061  i--;
18062  }
18063  else
18064  {
18065  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18066  }
18067  found = TRUE;
18068  }
18069  i++;
18070  }
18071 
18072  if( !found && !SCIPisZero(scip, val) )
18073  {
18074  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18075  }
18076 
18077  return SCIP_OKAY;
18078 }
18079 
18080 /** deletes variable from linear constraint
18081  *
18082  * @note This method may only be called during problem creation stage for an original constraint and variable.
18083  *
18084  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18085  */
18087  SCIP* scip, /**< SCIP data structure */
18088  SCIP_CONS* cons, /**< constraint data */
18089  SCIP_VAR* var /**< variable of constraint entry */
18090  )
18091 {
18092  assert(scip != NULL);
18093  assert(cons != NULL);
18094  assert(var != NULL);
18095 
18096  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18097 
18098  return SCIP_OKAY;
18099 }
18100 
18101 /** gets left hand side of linear constraint */
18103  SCIP* scip, /**< SCIP data structure */
18104  SCIP_CONS* cons /**< constraint data */
18105  )
18106 {
18107  SCIP_CONSDATA* consdata;
18108 
18109  assert(cons != NULL);
18110 
18111  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18112  {
18113  SCIPerrorMessage("constraint is not linear\n");
18114  SCIPABORT();
18115  return SCIP_INVALID; /*lint !e527*/
18116  }
18117 
18118  consdata = SCIPconsGetData(cons);
18119  assert(consdata != NULL);
18120 
18121  return consdata->lhs;
18122 }
18123 
18124 /** gets right hand side of linear constraint */
18126  SCIP* scip, /**< SCIP data structure */
18127  SCIP_CONS* cons /**< constraint data */
18128  )
18129 {
18130  SCIP_CONSDATA* consdata;
18131 
18132  assert(cons != NULL);
18133 
18134  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18135  {
18136  SCIPerrorMessage("constraint is not linear\n");
18137  SCIPABORT();
18138  return SCIP_INVALID; /*lint !e527*/
18139  }
18140 
18141  consdata = SCIPconsGetData(cons);
18142  assert(consdata != NULL);
18143 
18144  return consdata->rhs;
18145 }
18146 
18147 /** changes left hand side of linear constraint */
18149  SCIP* scip, /**< SCIP data structure */
18150  SCIP_CONS* cons, /**< constraint data */
18151  SCIP_Real lhs /**< new left hand side */
18152  )
18153 {
18154  assert(scip != NULL);
18155  assert(cons != NULL);
18156 
18157  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18158  {
18159  SCIPerrorMessage("constraint is not linear\n");
18160  return SCIP_INVALIDDATA;
18161  }
18162 
18163  SCIP_CALL( chgLhs(scip, cons, lhs) );
18164 
18165  return SCIP_OKAY;
18166 }
18167 
18168 /** changes right hand side of linear constraint */
18170  SCIP* scip, /**< SCIP data structure */
18171  SCIP_CONS* cons, /**< constraint data */
18172  SCIP_Real rhs /**< new right hand side */
18173  )
18174 {
18175  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18176  {
18177  SCIPerrorMessage("constraint is not linear\n");
18178  return SCIP_INVALIDDATA;
18179  }
18180 
18181  SCIP_CALL( chgRhs(scip, cons, rhs) );
18182 
18183  return SCIP_OKAY;
18184 }
18185 
18186 /** gets the number of variables in the linear constraint */
18187 int SCIPgetNVarsLinear(
18188  SCIP* scip, /**< SCIP data structure */
18189  SCIP_CONS* cons /**< constraint data */
18190  )
18191 {
18192  SCIP_CONSDATA* consdata;
18193 
18194  assert(cons != NULL);
18195 
18196  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18197  {
18198  SCIPerrorMessage("constraint is not linear\n");
18199  SCIPABORT();
18200  return -1; /*lint !e527*/
18201  }
18202 
18203  consdata = SCIPconsGetData(cons);
18204  assert(consdata != NULL);
18205 
18206  return consdata->nvars;
18207 }
18208 
18209 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18211  SCIP* scip, /**< SCIP data structure */
18212  SCIP_CONS* cons /**< constraint data */
18213  )
18214 {
18215  SCIP_CONSDATA* consdata;
18216 
18217  assert(cons != NULL);
18218 
18219  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18220  {
18221  SCIPerrorMessage("constraint is not linear\n");
18222  SCIPABORT();
18223  return NULL; /*lint !e527*/
18224  }
18225 
18226  consdata = SCIPconsGetData(cons);
18227  assert(consdata != NULL);
18228 
18229  return consdata->vars;
18230 }
18231 
18232 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18234  SCIP* scip, /**< SCIP data structure */
18235  SCIP_CONS* cons /**< constraint data */
18236  )
18237 {
18238  SCIP_CONSDATA* consdata;
18239 
18240  assert(cons != NULL);
18241 
18242  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18243  {
18244  SCIPerrorMessage("constraint is not linear\n");
18245  SCIPABORT();
18246  return NULL; /*lint !e527*/
18247  }
18248 
18249  consdata = SCIPconsGetData(cons);
18250  assert(consdata != NULL);
18251 
18252  return consdata->vals;
18253 }
18254 
18255 /** gets the activity of the linear constraint in the given solution
18256  *
18257  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18258  * comprises positive and negative infinity contributions
18259  */
18261  SCIP* scip, /**< SCIP data structure */
18262  SCIP_CONS* cons, /**< constraint data */
18263  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18264  )
18265 {
18266  SCIP_CONSDATA* consdata;
18267 
18268  assert(cons != NULL);
18269 
18270  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18271  {
18272  SCIPerrorMessage("constraint is not linear\n");
18273  SCIPABORT();
18274  return SCIP_INVALID; /*lint !e527*/
18275  }
18276 
18277  consdata = SCIPconsGetData(cons);
18278  assert(consdata != NULL);
18279 
18280  if( consdata->row != NULL )
18281  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18282  else
18283  return consdataGetActivity(scip, consdata, sol);
18284 }
18285 
18286 /** gets the feasibility of the linear constraint in the given solution */
18288  SCIP* scip, /**< SCIP data structure */
18289  SCIP_CONS* cons, /**< constraint data */
18290  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18291  )
18292 {
18293  SCIP_CONSDATA* consdata;
18294 
18295  assert(cons != NULL);
18296 
18297  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18298  {
18299  SCIPerrorMessage("constraint is not linear\n");
18300  SCIPABORT();
18301  return SCIP_INVALID; /*lint !e527*/
18302  }
18303 
18304  consdata = SCIPconsGetData(cons);
18305  assert(consdata != NULL);
18306 
18307  if( consdata->row != NULL )
18308  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18309  else
18310  return consdataGetFeasibility(scip, consdata, sol);
18311 }
18312 
18313 /** gets the dual solution of the linear constraint in the current LP */
18315  SCIP* scip, /**< SCIP data structure */
18316  SCIP_CONS* cons /**< constraint data */
18317  )
18318 {
18319  SCIP_CONSDATA* consdata;
18320 
18321  assert(cons != NULL);
18322  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18323 
18324  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18325  {
18326  SCIPerrorMessage("constraint is not linear\n");
18327  SCIPABORT();
18328  return SCIP_INVALID; /*lint !e527*/
18329  }
18330 
18331  consdata = SCIPconsGetData(cons);
18332  assert(consdata != NULL);
18333 
18334  if( consdata->row != NULL )
18335  return SCIProwGetDualsol(consdata->row);
18336  else
18337  return 0.0;
18338 }
18339 
18340 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18342  SCIP* scip, /**< SCIP data structure */
18343  SCIP_CONS* cons /**< constraint data */
18344  )
18345 {
18346  SCIP_CONSDATA* consdata;
18347 
18348  assert(cons != NULL);
18349  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18350 
18351  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18352  {
18353  SCIPerrorMessage("constraint is not linear\n");
18354  SCIPABORT();
18355  return SCIP_INVALID; /*lint !e527*/
18356  }
18357 
18358  consdata = SCIPconsGetData(cons);
18359  assert(consdata != NULL);
18360 
18361  if( consdata->row != NULL )
18362  return SCIProwGetDualfarkas(consdata->row);
18363  else
18364  return 0.0;
18365 }
18366 
18367 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18368  * the user must not modify the row!
18369  */
18371  SCIP* scip, /**< SCIP data structure */
18372  SCIP_CONS* cons /**< constraint data */
18373  )
18374 {
18375  SCIP_CONSDATA* consdata;
18376 
18377  assert(cons != NULL);
18378 
18379  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18380  {
18381  SCIPerrorMessage("constraint is not linear\n");
18382  SCIPABORT();
18383  return NULL; /*lint !e527*/
18384  }
18385 
18386  consdata = SCIPconsGetData(cons);
18387  assert(consdata != NULL);
18388 
18389  return consdata->row;
18390 }
18391 
18392 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18394  SCIP* scip, /**< SCIP data structure */
18395  SCIP_CONS* cons, /**< source constraint to try to convert */
18396  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18397  )
18398 {
18399  SCIP_CONSHDLR* conshdlr;
18400  SCIP_CONSHDLRDATA* conshdlrdata;
18401  SCIP_CONSDATA* consdata;
18402  SCIP_VAR* var;
18403  SCIP_Real val;
18404  SCIP_Real lb;
18405  SCIP_Real ub;
18406  SCIP_Real poscoeffsum;
18407  SCIP_Real negcoeffsum;
18408  SCIP_Bool infeasible;
18409  SCIP_Bool integral;
18410  int nposbin;
18411  int nnegbin;
18412  int nposint;
18413  int nnegint;
18414  int nposimpl;
18415  int nnegimpl;
18416  int nposimplbin;
18417  int nnegimplbin;
18418  int nposcont;
18419  int nnegcont;
18420  int ncoeffspone;
18421  int ncoeffsnone;
18422  int ncoeffspint;
18423  int ncoeffsnint;
18424  int ncoeffspfrac;
18425  int ncoeffsnfrac;
18426  int i;
18427 
18428  assert(scip != NULL);
18429  assert(cons != NULL);
18430  assert(upgdcons != NULL);
18431 
18432  *upgdcons = NULL;
18433 
18434  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18435  if( SCIPconsIsModifiable(cons) )
18436  return SCIP_OKAY;
18437 
18438  /* check for upgradability */
18439  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18440  return SCIP_OKAY;
18441 
18442  /* get the constraint handler and check, if it's really a linear constraint */
18443  conshdlr = SCIPconsGetHdlr(cons);
18444  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18445  {
18446  SCIPerrorMessage("constraint is not linear\n");
18447  return SCIP_INVALIDDATA;
18448  }
18449 
18450  /* get constraint handler data and constraint data */
18451  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18452  assert(conshdlrdata != NULL);
18453  consdata = SCIPconsGetData(cons);
18454  assert(consdata != NULL);
18455 
18456  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18457  if( consdata->upgraded )
18458  return SCIP_OKAY;
18459 
18460  /* check, if the constraint is already stored as LP row */
18461  if( consdata->row != NULL )
18462  {
18463  if( SCIProwIsInLP(consdata->row) )
18464  {
18465  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18466  return SCIP_INVALIDDATA;
18467  }
18468  else
18469  {
18470  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18471  }
18472  }
18473 
18474  /* normalize constraint */
18475  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18476 
18477  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18478  * skipped and we hope that the infeasibility gets detected later again.
18479  *
18480  * TODO: do we want to try to upgrade the constraint anyway?
18481  *
18482  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18483  * proven to be infeasible.
18484  */
18485  if( infeasible )
18486  return SCIP_OKAY;
18487 
18488  /*
18489  * calculate some statistics on linear constraint
18490  */
18491 
18492  nposbin = 0;
18493  nnegbin = 0;
18494  nposint = 0;
18495  nnegint = 0;
18496  nposimpl = 0;
18497  nnegimpl = 0;
18498  nposimplbin = 0;
18499  nnegimplbin = 0;
18500  nposcont = 0;
18501  nnegcont = 0;
18502  ncoeffspone = 0;
18503  ncoeffsnone = 0;
18504  ncoeffspint = 0;
18505  ncoeffsnint = 0;
18506  ncoeffspfrac = 0;
18507  ncoeffsnfrac = 0;
18508  integral = TRUE;
18509  poscoeffsum = 0.0;
18510  negcoeffsum = 0.0;
18511 
18512  for( i = 0; i < consdata->nvars; ++i )
18513  {
18514  var = consdata->vars[i];
18515  val = consdata->vals[i];
18516  lb = SCIPvarGetLbLocal(var);
18517  ub = SCIPvarGetUbLocal(var);
18518  assert(!SCIPisZero(scip, val));
18519 
18520  switch( SCIPvarGetType(var) )
18521  {
18522  case SCIP_VARTYPE_BINARY:
18523  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18524  integral = integral && SCIPisIntegral(scip, val);
18525  if( val >= 0.0 )
18526  nposbin++;
18527  else
18528  nnegbin++;
18529  break;
18530  case SCIP_VARTYPE_INTEGER:
18531  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18532  integral = integral && SCIPisIntegral(scip, val);
18533  if( val >= 0.0 )
18534  nposint++;
18535  else
18536  nnegint++;
18537  break;
18538  case SCIP_VARTYPE_IMPLINT:
18539  if( SCIPvarIsBinary(var) )
18540  {
18541  if( val >= 0.0 )
18542  nposimplbin++;
18543  else
18544  nnegimplbin++;
18545  }
18546  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18547  integral = integral && SCIPisIntegral(scip, val);
18548  if( val >= 0.0 )
18549  nposimpl++;
18550  else
18551  nnegimpl++;
18552  break;
18554  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18555  if( val >= 0.0 )
18556  nposcont++;
18557  else
18558  nnegcont++;
18559  break;
18560  default:
18561  SCIPerrorMessage("unknown variable type\n");
18562  return SCIP_INVALIDDATA;
18563  }
18564  if( SCIPisEQ(scip, val, 1.0) )
18565  ncoeffspone++;
18566  else if( SCIPisEQ(scip, val, -1.0) )
18567  ncoeffsnone++;
18568  else if( SCIPisIntegral(scip, val) )
18569  {
18570  if( SCIPisPositive(scip, val) )
18571  ncoeffspint++;
18572  else
18573  ncoeffsnint++;
18574  }
18575  else
18576  {
18577  if( SCIPisPositive(scip, val) )
18578  ncoeffspfrac++;
18579  else
18580  ncoeffsnfrac++;
18581  }
18582  if( SCIPisPositive(scip, val) )
18583  poscoeffsum += val;
18584  else
18585  negcoeffsum += val;
18586  }
18587 
18588  /*
18589  * call the upgrading methods
18590  */
18591 
18592  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18593  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18594  SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
18595  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18596  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18597  poscoeffsum, negcoeffsum, integral);
18598 
18599  /* try all upgrading methods in priority order in case the upgrading step is enable */
18600  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18601  {
18602  if( conshdlrdata->linconsupgrades[i]->active )
18603  {
18604  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18605  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18606  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18607  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18608  poscoeffsum, negcoeffsum, integral,
18609  upgdcons) );
18610  }
18611  }
18612 
18613 #ifdef SCIP_DEBUG
18614  if( *upgdcons != NULL )
18615  {
18616  SCIPdebugPrintCons(scip, cons, NULL);
18617  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18618  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18619  }
18620 #endif
18621 
18622  return SCIP_OKAY;
18623 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define EVENTHDLR_DESC
Definition: cons_linear.c:108
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:100
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:97
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8086
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:111
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Real SCIPfeastol(SCIP *scip)
struct InferInfo INFERINFO
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4221
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:86
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)
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2167
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:76
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_EXPORT SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16880
SCIP_Real SCIPepsilon(SCIP *scip)
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6705
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1431
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2396
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8469
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
#define NULL
Definition: def.h:253
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:686
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:585
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:855
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:406
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:719
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:80
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2364
SCIP_EXPORT SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16893
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3970
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:876
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3141
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16986
public methods for SCIP parameter handling
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:131
SCIP_EXPORT SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17098
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:119
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1994
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:220
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:452
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_NAME
Definition: cons_linear.c:89
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5121
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_cons.c:933
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8315
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:99
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
#define BINWEIGHT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3162
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:1598
SCIP_EXPORT int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3241
public methods for memory management
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:166
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:307
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1536
#define MAXSCALEDCOEF
Definition: cons_linear.c:173
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:128
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7718
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:115
#define DEFAULT_SORTVARS
Definition: cons_linear.c:125
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9367
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8275
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1950
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_cons.c:165
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4200
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:5345
static SCIP_RETCODE findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
#define SCIP_MAXSTRLEN
Definition: def.h:274
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1483
public methods for conflict handler plugins and conflict analysis
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:122
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:824
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2425
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:815
static long bound
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2056
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1217
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1352
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5237
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2031
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2285
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8690
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:509
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:769
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:117
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4593
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:417
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1299
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4186
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:160
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:746
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_var.c:5530
SCIP_EXPORT SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16918
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:314
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3037
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1987
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8137
#define NLOCKTYPES
Definition: type_var.h:81
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:2859
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3220
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:215
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:143
#define FALSE
Definition: def.h:73
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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)
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1200
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPORT SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17200
static SCIP_DECL_CONSCOPY(consCopyLinear)
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:2921
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_EXPORT SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16903
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:590
#define TRUE
Definition: def.h:72
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:137
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3083
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
enum Proprule PROPRULE
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:121
#define SCIPstatisticMessage
Definition: pub_message.h:104
static SCIP_DECL_CONSINITLP(consInitlpLinear)
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3470
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
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:7481
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3581
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:276
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:562
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
SCIP_EXPORT SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17025
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4583
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_param.c:47
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3692
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2494
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:122
SCIP_EXPORT SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16857
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1232
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:119
enum Proprule PROPRULE
Definition: cons_linear.c:356
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:524
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)
static SCIP_RETCODE aggregateConstraints(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *commonidx0, int *commonidx1, int *diffidx0minus1, int *diffidx1minus0, int nvarscommon, int commonidxweight, int diffidx0minus1weight, int diffidx1minus0weight, SCIP_Real maxaggrnormscale, int *nchgcoefs, SCIP_Bool *aggregated, SCIP_Bool *infeasible)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:380
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:415
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:135
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5732
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1257
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:838
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
#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:758
public methods for SCIP variables
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1531
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:500
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3207
#define SCIPdebugMsgPrint
Definition: scip_message.h:70
#define SCIPdebugMsg
Definition: scip_message.h:69
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2301
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2005
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17085
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:140
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4291
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8819
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:118
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:5014
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:558
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:104
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:356
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:73
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1460
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:105
SCIP_EXPORT void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:9527
public methods for numerical tolerances
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_EXPORT SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17144
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:2113
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2838
public methods for querying solving statistics
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8415
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:94
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17177
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define MAXCONSPRESOLROUNDS
public methods for the branch-and-bound tree
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_copy.c:672
static SCIP_DECL_EVENTEXEC(eventExecLinear)
SCIP_EXPORT SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16939
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:530
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5223
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:7144
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_VAR * w
Definition: circlepacking.c:58
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:92
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:110
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10571
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:150
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
static SCIP_DECL_CONSDELETE(consDeleteLinear)
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_var.c:1740
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:112
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:404
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
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:5276
SCIP_EXPORT const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16738
SCIP_EXPORT void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
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:2482
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
SCIP_EXPORT SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16929
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:495
#define SCIPerrorMessage
Definition: pub_message.h:45
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:95
SCIP_EXPORT SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17168
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1406
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
public methods for event handler plugins and event handlers
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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:2581
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2215
#define COPYSIGN
Definition: def.h:244
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:595
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1942
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5087
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3223
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1407
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1442
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:509
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:168
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3567
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:449
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:47
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2129
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3293
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2079
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:397
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:8940
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
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_var.c:8439
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:87
constraint handler for quadratic constraints
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5079
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8489
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3849
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:5130
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:434
#define REALABS(x)
Definition: def.h:188
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:620
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:101
public methods for problem copies
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:622
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8106
#define SCIP_CALL(x)
Definition: def.h:365
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5247
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:631
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:93
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5414
#define SCIPhashSignature64(a)
Definition: pub_misc.h:492
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:995
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1198
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:2381
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
Definition: grphload.c:88
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4043
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:257
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:51
SCIP_EXPORT SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17109
static SCIP_DECL_CONSTRANS(consTransLinear)
SCIP_EXPORT SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17189
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
public methods for constraint handler plugins and constraints
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:259
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7571
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1748
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2186
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:155
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8345
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1089
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
#define QUADCONSUPGD_PRIORITY
Definition: cons_linear.c:184
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:111
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16999
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
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)
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:129
SCIP_Real SCIPinfinity(SCIP *scip)
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_cons.c:219
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3441
SCIP_EXPORT SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17178
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1174
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4376
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2163
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8435
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:637
SCIP_EXPORT void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:390
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5348
SCIP_EXPORT SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17156
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:102
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:96
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1207
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:7940
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4127
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:331
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1380
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1267
SCIP_EXPORT SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17362
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3073
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2472
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6973
constraint handler for nonlinear constraints
SCIP_EXPORT SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17464
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:568
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:147
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8963
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:90
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4211
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:145
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4518
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip_var.c:8506
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7428
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_var.c:104
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_EXPORT SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16867
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
#define MIN(x, y)
Definition: def.h:223
methods for debugging
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1307
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_lp.c:1268
public methods for LP management
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8425
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5317
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8385
public methods for cuts and aggregation rows
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2033
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1246
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2319
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:185
static int getVarWeight(SCIP_VAR *var)
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
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_var.c:699
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:124
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8255
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:761
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8180
int SCIPgetNSepaRounds(SCIP *scip)
#define MAXDNOM
Definition: cons_linear.c:172
SCIP_EXPORT SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16959
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8527
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1667
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:116
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8335
Proprule
SCIP_EXPORT SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17408
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:114
#define SCIP_MAXTREEDEPTH
Definition: def.h:301
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:94
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_param.c:129
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1978
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
public methods for the LP relaxation, rows and columns
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2130
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:144
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7404
#define MINVALRECOMP
Definition: cons_linear.c:181
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:91
SCIP_EXPORT int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3184
#define SCIP_REAL_MAX
Definition: def.h:165
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2627
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1326
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:174
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_EXPORT SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17418
methods for sorting joint arrays of various types
static SCIP_DECL_CONSCHECK(consCheckLinear)
#define SCIP_LONGINT_FORMAT
Definition: def.h:156
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:544
public methods for branching rule plugins and branching
SCIP_VAR ** b
Definition: circlepacking.c:56
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3187
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:220
static SCIP_DECL_CONSPARSE(consParseLinear)
public methods for managing events
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5674
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:652
general public methods
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_var.c:5417
SCIP_EXPORT SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17954
#define MAX(x, y)
Definition: def.h:222
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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:2708
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
public methods for solutions
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4451
static const SCIP_Real scalars[]
Definition: lp.c:5650
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1451
#define CONTWEIGHT
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1427
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8265
static SCIP_DECL_CONSLOCK(consLockLinear)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1460
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:792
SCIP_Real SCIPgetLowerbound(SCIP *scip)
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
public methods for conflict analysis handlers
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:7853
SCIP_EXPORT SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17352
public methods for the probing mode
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_DECL_CONSPRINT(consPrintLinear)
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:677
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1539
SCIP_EXPORT int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17120
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4563
public methods for message output
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip_var.c:6831
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10263
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2621
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_param.c:73
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9423
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:111
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1251
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9378
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8205
#define SCIP_Real
Definition: def.h:164
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6977
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:59
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_conflict.c:98
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9481
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:146
#define EVENTHDLR_NAME
Definition: cons_linear.c:107
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8096
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:92
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4589
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for message handling
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1128
static unsigned int getParallelConsKey(SCIP_CONS *cons)
SCIP_EXPORT SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12268
#define SCIP_INVALID
Definition: def.h:184
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:163
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3695
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:90
#define SCIP_Longint
Definition: def.h:149
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8355
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4191
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:474
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:256
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:333
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2032
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1796
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:344
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7786
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1353
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1018
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8375
SCIP_EXPORT int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17045
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2765
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9537
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:50
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1720
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:98
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:388
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:7971
#define MAXVALRECOMP
Definition: cons_linear.c:180
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:685
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3389
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:120
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8285
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1565
SCIP_EXPORT SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17087
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:134
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:198
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:427
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_var.c:6692
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1696
#define SCIP_CALL_ABORT(x)
Definition: def.h:344
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1109
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
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_var.c:8305
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8084
static SCIP_DECL_CONSEXIT(consExitLinear)
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:165
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:355
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:792
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:265
SCIP_EXPORT SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16949
#define SCIPcombineTwoInt(a, b)
Definition: pub_misc.h:499
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8942
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8469
#define SCIPABORT()
Definition: def.h:337
public methods for global and local (sub)problems
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4551
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:375
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8295
#define INTWEIGHT
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:1754
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4832
#define ABS(x)
Definition: def.h:218
SCIP_EXPORT SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17132
SCIP_EXPORT SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17944
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:57
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1983
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:608
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
SCIP_EXPORT int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17035
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:120
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8325
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
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:2008
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1054
SCIP_EXPORT int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11436
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:1982
int SCIPgetNRuns(SCIP *scip)
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:107
memory allocation routines
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:164
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)