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-2022 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 scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @ingroup DEFPLUGINS_CONS
18  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Marc Pfetsch
22  * @author Kati Wolter
23  * @author Michael Winkler
24  * @author Gerald Gamrath
25  * @author Domenico Salvagnin
26  *
27  * Linear constraints are separated with a high priority, because they are easy
28  * to separate. Instead of using the global cut pool, the same effect can be
29  * implemented by adding linear constraints to the root node, such that they are
30  * separated each time, the linear constraints are separated. A constraint
31  * handler, which generates linear constraints in this way should have a lower
32  * separation priority than the linear constraint handler, and it should have a
33  * separation frequency that is a multiple of the frequency of the linear
34  * constraint handler. In this way, it can be avoided to separate the same cut
35  * twice, because if a separation run of the handler is always preceded by a
36  * separation of the linear constraints, the priorily added constraints are
37  * always satisfied.
38  *
39  * Linear constraints are enforced and checked with a very low priority. Checking
40  * of (many) linear constraints is much more involved than checking the solution
41  * values for integrality. Because we are separating the linear constraints quite
42  * often, it is only necessary to enforce them for integral solutions. A constraint
43  * handler which generates pool cuts in its enforcing method should have an
44  * enforcing priority smaller than that of the linear constraint handler to avoid
45  * regenerating constraints which already exist.
46  */
47 
48 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49 
50 #include "blockmemshell/memory.h"
51 #include "scip/cons_nonlinear.h"
52 #include "scip/cons_knapsack.h"
53 #include "scip/cons_linear.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_expr.h"
59 #include "scip/pub_lp.h"
60 #include "scip/pub_message.h"
61 #include "scip/pub_misc.h"
62 #include "scip/pub_misc_sort.h"
63 #include "scip/pub_var.h"
64 #include "scip/scip_branch.h"
65 #include "scip/scip_conflict.h"
66 #include "scip/scip_cons.h"
67 #include "scip/scip_copy.h"
68 #include "scip/scip_cut.h"
69 #include "scip/scip_event.h"
70 #include "scip/scip_general.h"
71 #include "scip/scip_lp.h"
72 #include "scip/scip_mem.h"
73 #include "scip/scip_message.h"
74 #include "scip/scip_numerics.h"
75 #include "scip/scip_param.h"
76 #include "scip/scip_prob.h"
77 #include "scip/scip_probing.h"
78 #include "scip/scip_sol.h"
79 #include "scip/scip_solvingstats.h"
80 #include "scip/scip_tree.h"
81 #include "scip/scip_var.h"
82 #include <ctype.h>
83 #include <string.h>
84 #if defined(_WIN32) || defined(_WIN64)
85 #else
86 #include <strings.h> /*lint --e{766}*/
87 #endif
88 
89 
90 #define CONSHDLR_NAME "linear"
91 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
92 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
93 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
94 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
95 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
96 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
97 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
98  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
99 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
100 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
101 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
102 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
104 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
105 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
107 #define EVENTHDLR_NAME "linear"
108 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
110 #define CONFLICTHDLR_NAME "linear"
111 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
112 #define CONFLICTHDLR_PRIORITY -1000000
114 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
115 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
116 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
117 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
118 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
119 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
120 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
121 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
122 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
123  * comparison round */
124 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
125  * propagation? */
126 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
127  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
128 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
129  * (0.0: disable constraint aggregation) */
130 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
131  * (faster, but numerically less stable) */
132 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
133  * to best node's dual bound for separating knapsack cardinality cuts */
134 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
135  * the ones with non-zero dual value? */
136 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
137 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
138 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
139 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
140 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
141  * constraints using the cheapest variable? */
142 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
143  * function defining an upper bound and prevent these constraints from
144  * entering the LP */
145 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
146  * function defining a lower bound and prevent these constraints from
147  * entering the LP */
148 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
149  * objective function */
150 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
151 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
152 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
153 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
154 
155 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
156  * removed afterwards? */
157 #define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
158 #define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
159 #define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
160 
161 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
162 #define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
163 #define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
164  * type
165  */
166 #define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
167  * redundancy-based simplifications are allowed to be applied
168  */
170 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
171 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
174 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
175 
176 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
177  * maybe in fullDualPresolve(), see convertLongEquality()
178  */
179 
180 
181 /** constraint data for linear constraints */
182 struct SCIP_ConsData
183 {
184  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
185  SCIP_Real rhs; /**< right hand side of row */
186  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
187  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
188  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
189  * activity, ignoring the coefficients contributing with infinite value */
190  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
191  * activity, ignoring the coefficients contributing with infinite value */
192  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
193  * over all contributing values */
194  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
195  * over all contributing values */
196  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
197  * activity, ignoring the coefficients contributing with infinite value */
198  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
199  * activity, ignoring the coefficients contributing with infinite value */
200  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
201  * over all contributing values */
202  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
203  * over all contributing values */
204  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
205  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
206  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
207  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
208  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
209  SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
210  SCIP_VAR** vars; /**< variables of constraint entries */
211  SCIP_Real* vals; /**< coefficients of constraint entries */
212  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
213  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
214  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
215  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
216  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
217  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
218  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
219  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
220  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
221  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
222  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
223  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
224  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
225  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
226  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
227  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
228  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
229  int varssize; /**< size of the vars- and vals-arrays */
230  int nvars; /**< number of nonzeros in constraint */
231  int nbinvars; /**< the number of binary variables in the constraint, only valid after
232  * sorting in stage >= SCIP_STAGE_INITSOLVE
233  */
234  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
235  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
236  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
237  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
238  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
239  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
240  unsigned int validminact:1; /**< is the local minactivity valid? */
241  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
242  unsigned int validglbminact:1; /**< is the global minactivity valid? */
243  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
244  unsigned int presolved:1; /**< is constraint already presolved? */
245  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
246  unsigned int validsignature:1; /**< is the bit signature valid? */
247  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
248  unsigned int normalized:1; /**< is the constraint in normalized form? */
249  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
250  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
251  unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
252  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
253  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
254  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
255  unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
256  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
257  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
258  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
259  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
260  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
261 };
262 
263 /** event data for bound change event */
264 struct SCIP_EventData
265 {
266  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
267  int varpos; /**< position of variable in vars array */
268  int filterpos; /**< position of event in variable's event filter */
269 };
270 
271 /** constraint handler data */
272 struct SCIP_ConshdlrData
273 {
274  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
275  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
276  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
277  * (0.0: disable constraint aggregation) */
278  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
279  * to best node's dual bound for separating knapsack cardinality cuts */
280  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
281  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
282  * (faster, but numerically less stable) */
283  int linconsupgradessize;/**< size of linconsupgrade array */
284  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
285  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
286  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
287  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
288  int maxsepacuts; /**< maximal number of cuts separated per separation round */
289  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
290  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
291  int naddconss; /**< number of added constraints */
292  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
293  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
294  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
295  * the ones with non-zero dual value? */
296  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
297  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
298  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
299  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
300  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
301  * constraints using the cheapest variable? */
302  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
303  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
304  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
305  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
306  * function defining an upper bound and prevent these constraints from
307  * entering the LP */
308  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
309  * function defining a lower bound and prevent these constraints from
310  * entering the LP */
311  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
312  * the objective function */
313  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
314  * infeasibility, and extract sub-constraints from ranged rows and
315  * equations */
316  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
317  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
318  int rangedrowfreq; /**< frequency for applying ranged row propagation */
319  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
320  * removed afterwards? */
321  SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
322  SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
323  SCIP_Bool extractcliques; /**< should cliques be extracted? */
324 };
325 
326 /** linear constraint update method */
327 struct SCIP_LinConsUpgrade
328 {
329  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
330  int priority; /**< priority of upgrading method */
331  SCIP_Bool active; /**< is upgrading enabled */
332 };
333 
334 
335 /*
336  * Propagation rules
337  */
338 
339 enum Proprule
340 {
341  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
342  * variable due to the right hand side of the inequality */
343  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
344  * variable due to the left hand side of the inequality */
345  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
346  * single variable in this reanged row */
347  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
348 };
349 typedef enum Proprule PROPRULE;
351 /** inference information */
352 struct InferInfo
353 {
354  union
355  {
356  struct
357  {
358  unsigned int proprule:8; /**< propagation rule that was applied */
359  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
360  } asbits;
361  int asint; /**< inference information as a single int value */
362  } val;
363 };
364 typedef struct InferInfo INFERINFO;
365 
366 /** converts an integer into an inference information */
367 static
369  int i /**< integer to convert */
370  )
371 {
372  INFERINFO inferinfo;
373 
374  inferinfo.val.asint = i;
375 
376  return inferinfo;
377 }
378 
379 /** converts an inference information into an int */
380 static
381 int inferInfoToInt(
382  INFERINFO inferinfo /**< inference information to convert */
383  )
384 {
385  return inferinfo.val.asint;
386 }
388 /** returns the propagation rule stored in the inference information */
389 static
391  INFERINFO inferinfo /**< inference information to convert */
392  )
393 {
394  return (int) inferinfo.val.asbits.proprule;
395 }
396 
397 /** returns the position stored in the inference information */
398 static
399 int inferInfoGetPos(
400  INFERINFO inferinfo /**< inference information to convert */
401  )
402 {
403  return (int) inferinfo.val.asbits.pos;
404 }
405 
406 /** constructs an inference information out of a propagation rule and a position number */
407 static
409  PROPRULE proprule, /**< propagation rule that deduced the value */
410  int pos /**< variable position, the propagation rule was applied at */
411  )
412 {
413  INFERINFO inferinfo;
414 
415  assert(pos >= 0);
416  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
417  assert(pos < (1<<24));
419  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
420  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
421 
422  return inferinfo;
423 }
424 
425 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
426 static
428  PROPRULE proprule, /**< propagation rule that deduced the value */
429  int pos /**< variable position, the propagation rule was applied at */
430  )
431 {
432  return inferInfoToInt(getInferInfo(proprule, pos));
433 }
434 
435 
436 /*
437  * memory growing methods for dynamically allocated arrays
438  */
439 
440 /** ensures, that linconsupgrades array can store at least num entries */
441 static
443  SCIP* scip, /**< SCIP data structure */
444  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
445  int num /**< minimum number of entries to store */
446  )
447 {
448  assert(scip != NULL);
449  assert(conshdlrdata != NULL);
450  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
451 
452  if( num > conshdlrdata->linconsupgradessize )
453  {
454  int newsize;
455 
456  newsize = SCIPcalcMemGrowSize(scip, num);
457  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
458  conshdlrdata->linconsupgradessize = newsize;
459  }
460  assert(num <= conshdlrdata->linconsupgradessize);
462  return SCIP_OKAY;
463 }
464 
465 /** ensures, that vars and vals arrays can store at least num entries */
466 static
468  SCIP* scip, /**< SCIP data structure */
469  SCIP_CONSDATA* consdata, /**< linear constraint data */
470  int num /**< minimum number of entries to store */
471  )
472 {
473  assert(scip != NULL);
474  assert(consdata != NULL);
475  assert(consdata->nvars <= consdata->varssize);
476 
477  if( num > consdata->varssize )
478  {
479  int newsize;
480 
481  newsize = SCIPcalcMemGrowSize(scip, num);
482  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
483  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
484  if( consdata->eventdata != NULL )
485  {
486  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
487  }
488  consdata->varssize = newsize;
489  }
490  assert(num <= consdata->varssize);
491 
492  return SCIP_OKAY;
493 }
494 
495 
496 /*
497  * local methods for managing linear constraint update methods
498  */
499 
500 /** creates a linear constraint upgrade data object */
501 static
503  SCIP* scip, /**< SCIP data structure */
504  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
505  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
506  int priority /**< priority of upgrading method */
507  )
508 {
509  assert(scip != NULL);
510  assert(linconsupgrade != NULL);
511  assert(linconsupgd != NULL);
512 
513  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
514  (*linconsupgrade)->linconsupgd = linconsupgd;
515  (*linconsupgrade)->priority = priority;
516  (*linconsupgrade)->active = TRUE;
517 
518  return SCIP_OKAY;
519 }
520 
521 /** frees a linear constraint upgrade data object */
522 static
523 void linconsupgradeFree(
524  SCIP* scip, /**< SCIP data structure */
525  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
526  )
527 {
528  assert(scip != NULL);
529  assert(linconsupgrade != NULL);
530  assert(*linconsupgrade != NULL);
531 
532  SCIPfreeBlockMemory(scip, linconsupgrade);
533 }
534 
535 /** creates constraint handler data for linear constraint handler */
536 static
538  SCIP* scip, /**< SCIP data structure */
539  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
540  SCIP_EVENTHDLR* eventhdlr /**< event handler */
541  )
542 {
543  assert(scip != NULL);
544  assert(conshdlrdata != NULL);
545  assert(eventhdlr != NULL);
546 
547  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
548  (*conshdlrdata)->linconsupgrades = NULL;
549  (*conshdlrdata)->linconsupgradessize = 0;
550  (*conshdlrdata)->nlinconsupgrades = 0;
551  (*conshdlrdata)->naddconss = 0;
552 
553  /* set event handler for updating linear constraint activity bounds */
554  (*conshdlrdata)->eventhdlr = eventhdlr;
555 
556  return SCIP_OKAY;
557 }
558 
559 /** frees constraint handler data for linear constraint handler */
560 static
561 void conshdlrdataFree(
562  SCIP* scip, /**< SCIP data structure */
563  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
564  )
565 {
566  int i;
567 
568  assert(scip != NULL);
569  assert(conshdlrdata != NULL);
570  assert(*conshdlrdata != NULL);
571 
572  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
573  {
574  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
575  }
576  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
577 
578  SCIPfreeBlockMemory(scip, conshdlrdata);
579 }
581 /** creates a linear constraint upgrade data object */
582 static
584  SCIP* scip, /**< SCIP data structure */
585  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
586  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
587  const char* conshdlrname /**< name of the constraint handler */
588  )
589 {
590  int i;
591 
592  assert(scip != NULL);
593  assert(conshdlrdata != NULL);
594  assert(linconsupgd != NULL);
595  assert(conshdlrname != NULL);
596 
597  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
598  {
599  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
600  {
601 #ifdef SCIP_DEBUG
602  SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
603 #endif
604  return TRUE;
605  }
606  }
607 
608  return FALSE;
609 }
610 
611 /** adds a linear constraint update method to the constraint handler's data */
612 static
614  SCIP* scip, /**< SCIP data structure */
615  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
616  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
617  )
618 {
619  int i;
620 
621  assert(scip != NULL);
622  assert(conshdlrdata != NULL);
623  assert(linconsupgrade != NULL);
624 
625  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
626 
627  for( i = conshdlrdata->nlinconsupgrades;
628  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
629  {
630  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
631  }
632  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
633  conshdlrdata->linconsupgrades[i] = linconsupgrade;
634  conshdlrdata->nlinconsupgrades++;
635 
636  return SCIP_OKAY;
637 }
638 
639 /*
640  * local methods
641  */
642 
643 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
644 static
646  SCIP* scip, /**< SCIP data structure */
647  SCIP_CONS* cons, /**< linear constraint */
648  SCIP_VAR* var, /**< variable of constraint entry */
649  SCIP_Real val /**< coefficient of constraint entry */
650  )
651 {
652  SCIP_CONSDATA* consdata;
653 
654  assert(scip != NULL);
655  assert(cons != NULL);
656  assert(var != NULL);
657 
658  consdata = SCIPconsGetData(cons);
659  assert(consdata != NULL);
660  assert(!SCIPisZero(scip, val));
661 
662  if( SCIPisPositive(scip, val) )
663  {
664  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
665  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
666  }
667  else
668  {
669  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
670  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
671  }
672 
673  return SCIP_OKAY;
674 }
675 
676 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
677 static
679  SCIP* scip, /**< SCIP data structure */
680  SCIP_CONS* cons, /**< linear constraint */
681  SCIP_VAR* var, /**< variable of constraint entry */
682  SCIP_Real val /**< coefficient of constraint entry */
683  )
684 {
685  SCIP_CONSDATA* consdata;
686 
687  assert(scip != NULL);
688  assert(cons != NULL);
689  assert(var != NULL);
690 
691  consdata = SCIPconsGetData(cons);
692  assert(consdata != NULL);
693  assert(!SCIPisZero(scip, val));
694 
695  if( SCIPisPositive(scip, val) )
696  {
697  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
698  !SCIPisInfinity(scip, consdata->rhs)) );
699  }
700  else
701  {
702  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
703  !SCIPisInfinity(scip, -consdata->lhs)) );
704  }
705 
706  return SCIP_OKAY;
707 }
708 
709 /** creates event data for variable at given position, and catches events */
710 /**! [SnippetDebugAssertions] */
711 static
713  SCIP* scip, /**< SCIP data structure */
714  SCIP_CONS* cons, /**< linear constraint */
715  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
716  int pos /**< array position of variable to catch bound change events for */
717  )
718 {
719  SCIP_CONSDATA* consdata;
720  assert(scip != NULL);
721  assert(cons != NULL);
722  assert(eventhdlr != NULL);
723 
724  consdata = SCIPconsGetData(cons);
725  assert(consdata != NULL);
726 
727  assert(0 <= pos && pos < consdata->nvars);
728  assert(consdata->vars != NULL);
729  assert(consdata->vars[pos] != NULL);
730  assert(SCIPvarIsTransformed(consdata->vars[pos]));
731  assert(consdata->eventdata != NULL);
732  assert(consdata->eventdata[pos] == NULL);
733 
734  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
735  consdata->eventdata[pos]->cons = cons;
736  consdata->eventdata[pos]->varpos = pos;
737 
738  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
741  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
742 
743  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
744 
745  return SCIP_OKAY;
746 }
747 /**! [SnippetDebugAssertions] */
748 
749 /** deletes event data for variable at given position, and drops events */
750 static
752  SCIP* scip, /**< SCIP data structure */
753  SCIP_CONS* cons, /**< linear constraint */
754  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
755  int pos /**< array position of variable to catch bound change events for */
756  )
757 {
758  SCIP_CONSDATA* consdata;
759  assert(scip != NULL);
760  assert(cons != NULL);
761  assert(eventhdlr != NULL);
762 
763  consdata = SCIPconsGetData(cons);
764  assert(consdata != NULL);
765 
766  assert(0 <= pos && pos < consdata->nvars);
767  assert(consdata->vars[pos] != NULL);
768  assert(consdata->eventdata != NULL);
769  assert(consdata->eventdata[pos] != NULL);
770  assert(consdata->eventdata[pos]->cons == cons);
771  assert(consdata->eventdata[pos]->varpos == pos);
772 
773  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
776  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
777 
778  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
779 
780  return SCIP_OKAY;
781 }
782 
783 /** catches bound change events for all variables in transformed linear constraint */
784 static
786  SCIP* scip, /**< SCIP data structure */
787  SCIP_CONS* cons, /**< linear constraint */
788  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
789  )
790 {
791  SCIP_CONSDATA* consdata;
792  int i;
793 
794  assert(scip != NULL);
795  assert(cons != NULL);
796 
797  consdata = SCIPconsGetData(cons);
798  assert(consdata != NULL);
799  assert(consdata->eventdata == NULL);
800 
801  /* allocate eventdata array */
802  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
803  assert(consdata->eventdata != NULL);
804  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
805 
806  /* catch event for every single variable */
807  for( i = 0; i < consdata->nvars; ++i )
808  {
809  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
810  }
811 
812  return SCIP_OKAY;
813 }
814 
815 /** drops bound change events for all variables in transformed linear constraint */
816 static
818  SCIP* scip, /**< SCIP data structure */
819  SCIP_CONS* cons, /**< linear constraint */
820  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
821  )
822 {
823  SCIP_CONSDATA* consdata;
824  int i;
825 
826  assert(scip != NULL);
827  assert(cons != NULL);
828 
829  consdata = SCIPconsGetData(cons);
830  assert(consdata != NULL);
831  assert(consdata->eventdata != NULL);
832 
833  /* drop event of every single variable */
834  for( i = consdata->nvars - 1; i >= 0; --i )
835  {
836  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
837  }
838 
839  /* free eventdata array */
840  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
841  assert(consdata->eventdata == NULL);
842 
843  return SCIP_OKAY;
844 }
845 
846 /** creates a linear constraint data */
847 static
849  SCIP* scip, /**< SCIP data structure */
850  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
851  int nvars, /**< number of nonzeros in the constraint */
852  SCIP_VAR** vars, /**< array with variables of constraint entries */
853  SCIP_Real* vals, /**< array with coefficients of constraint entries */
854  SCIP_Real lhs, /**< left hand side of row */
855  SCIP_Real rhs /**< right hand side of row */
856  )
857 {
858  int v;
859  SCIP_Real constant;
860 
861  assert(scip != NULL);
862  assert(consdata != NULL);
863  assert(nvars == 0 || vars != NULL);
864  assert(nvars == 0 || vals != NULL);
865 
866  if( SCIPisInfinity(scip, rhs) )
867  rhs = SCIPinfinity(scip);
868  else if( SCIPisInfinity(scip, -rhs) )
869  rhs = -SCIPinfinity(scip);
870 
871  if( SCIPisInfinity(scip, -lhs) )
872  lhs = -SCIPinfinity(scip);
873  else if( SCIPisInfinity(scip, lhs) )
874  lhs = SCIPinfinity(scip);
875 
876  if( SCIPisGT(scip, lhs, rhs) )
877  {
878  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
879  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
880  }
881 
882  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
883 
884  (*consdata)->varssize = 0;
885  (*consdata)->nvars = nvars;
886  (*consdata)->hascontvar = FALSE;
887  (*consdata)->hasnonbinvar = FALSE;
888  (*consdata)->hasnonbinvalid = TRUE;
889  (*consdata)->vars = NULL;
890  (*consdata)->vals = NULL;
891 
892  constant = 0.0;
893  if( nvars > 0 )
894  {
895  int k;
896 
897  SCIP_VAR** varsbuffer;
898  SCIP_Real* valsbuffer;
899 
900  /* copy variables into temporary buffer */
901  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
902  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
903  k = 0;
904 
905  /* loop over variables and sort out fixed ones */
906  for( v = 0; v < nvars; ++v )
907  {
908  SCIP_VAR* var;
909  SCIP_Real val;
910 
911  var = vars[v];
912  val = vals[v];
913 
914  assert(var != NULL);
915  if( !SCIPisZero(scip, val) )
916  {
917  /* treat fixed variable as a constant if problem compression is enabled */
919  {
920  constant += SCIPvarGetLbGlobal(var) * val;
921  }
922  else
923  {
924  varsbuffer[k] = var;
925  valsbuffer[k] = val;
926  k++;
927 
928  /* update hascontvar and hasnonbinvar flags */
929  if( !(*consdata)->hascontvar )
930  {
931  SCIP_VARTYPE vartype = SCIPvarGetType(var);
932 
933  if( vartype != SCIP_VARTYPE_BINARY )
934  {
935  (*consdata)->hasnonbinvar = TRUE;
936 
937  if( vartype == SCIP_VARTYPE_CONTINUOUS )
938  (*consdata)->hascontvar = TRUE;
939  }
940  }
941  }
942  }
943  }
944  (*consdata)->nvars = k;
945 
946  if( k > 0 )
947  {
948  /* copy the possibly reduced buffer arrays into block */
949  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
950  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
951  (*consdata)->varssize = k;
952  }
953  /* free temporary buffer */
954  SCIPfreeBufferArray(scip, &valsbuffer);
955  SCIPfreeBufferArray(scip, &varsbuffer);
956  }
957 
958  (*consdata)->eventdata = NULL;
959 
960  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
961  if( !SCIPisZero(scip, constant) )
962  {
963  if( !SCIPisInfinity(scip, REALABS(lhs)) )
964  lhs -= constant;
965 
966  if( !SCIPisInfinity(scip, REALABS(rhs)) )
967  rhs -= constant;
968  }
969 
970  (*consdata)->row = NULL;
971  (*consdata)->nlrow = NULL;
972  (*consdata)->lhs = lhs;
973  (*consdata)->rhs = rhs;
974  (*consdata)->maxabsval = SCIP_INVALID;
975  (*consdata)->minabsval = SCIP_INVALID;
976  (*consdata)->minactivity = SCIP_INVALID;
977  (*consdata)->maxactivity = SCIP_INVALID;
978  (*consdata)->lastminactivity = SCIP_INVALID;
979  (*consdata)->lastmaxactivity = SCIP_INVALID;
980  (*consdata)->maxactdelta = SCIP_INVALID;
981  (*consdata)->maxactdeltavar = NULL;
982  (*consdata)->minactivityneginf = -1;
983  (*consdata)->minactivityposinf = -1;
984  (*consdata)->maxactivityneginf = -1;
985  (*consdata)->maxactivityposinf = -1;
986  (*consdata)->minactivityneghuge = -1;
987  (*consdata)->minactivityposhuge = -1;
988  (*consdata)->maxactivityneghuge = -1;
989  (*consdata)->maxactivityposhuge = -1;
990  (*consdata)->glbminactivity = SCIP_INVALID;
991  (*consdata)->glbmaxactivity = SCIP_INVALID;
992  (*consdata)->lastglbminactivity = SCIP_INVALID;
993  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
994  (*consdata)->glbminactivityneginf = -1;
995  (*consdata)->glbminactivityposinf = -1;
996  (*consdata)->glbmaxactivityneginf = -1;
997  (*consdata)->glbmaxactivityposinf = -1;
998  (*consdata)->glbminactivityneghuge = -1;
999  (*consdata)->glbminactivityposhuge = -1;
1000  (*consdata)->glbmaxactivityneghuge = -1;
1001  (*consdata)->glbmaxactivityposhuge = -1;
1002  (*consdata)->possignature = 0;
1003  (*consdata)->negsignature = 0;
1004  (*consdata)->validmaxabsval = FALSE;
1005  (*consdata)->validminabsval = FALSE;
1006  (*consdata)->validactivities = FALSE;
1007  (*consdata)->validminact = FALSE;
1008  (*consdata)->validmaxact = FALSE;
1009  (*consdata)->validglbminact = FALSE;
1010  (*consdata)->validglbmaxact = FALSE;
1011  (*consdata)->boundstightened = 0;
1012  (*consdata)->presolved = FALSE;
1013  (*consdata)->removedfixings = FALSE;
1014  (*consdata)->validsignature = FALSE;
1015  (*consdata)->changed = TRUE;
1016  (*consdata)->normalized = FALSE;
1017  (*consdata)->upgradetried = FALSE;
1018  (*consdata)->upgraded = FALSE;
1019  (*consdata)->indexsorted = (nvars <= 1);
1020  (*consdata)->merged = (nvars <= 1);
1021  (*consdata)->cliquesadded = FALSE;
1022  (*consdata)->implsadded = FALSE;
1023  (*consdata)->coefsorted = FALSE;
1024  (*consdata)->nbinvars = -1;
1025  (*consdata)->varsdeleted = FALSE;
1026  (*consdata)->rangedrowpropagated = 0;
1027  (*consdata)->checkabsolute = FALSE;
1028 
1029  if( SCIPisTransformed(scip) )
1030  {
1031  /* get transformed variables */
1032  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1033  }
1034 
1035  /* capture variables */
1036  for( v = 0; v < (*consdata)->nvars; v++ )
1037  {
1038  /* likely implies a deleted variable */
1039  if( (*consdata)->vars[v] == NULL )
1040  {
1041  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1042  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1043  SCIPfreeBlockMemory(scip, consdata);
1044  return SCIP_INVALIDDATA;
1045  }
1046 
1047  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1048  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1049  }
1050 
1051  return SCIP_OKAY;
1052 }
1053 
1054 /** frees a linear constraint data */
1055 static
1057  SCIP* scip, /**< SCIP data structure */
1058  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1059  )
1060 {
1061  int v;
1062 
1063  assert(scip != NULL);
1064  assert(consdata != NULL);
1065  assert(*consdata != NULL);
1066  assert((*consdata)->varssize >= 0);
1067 
1068  /* release the row */
1069  if( (*consdata)->row != NULL )
1070  {
1071  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1072  }
1073 
1074  /* release the nlrow */
1075  if( (*consdata)->nlrow != NULL )
1076  {
1077  SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1078  }
1079 
1080  /* release variables */
1081  for( v = 0; v < (*consdata)->nvars; v++ )
1082  {
1083  assert((*consdata)->vars[v] != NULL);
1084  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1085  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1086  }
1087 
1088  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1089  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1090  SCIPfreeBlockMemory(scip, consdata);
1091 
1092  return SCIP_OKAY;
1093 }
1094 
1095 /** prints linear constraint in CIP format to file stream */
1096 static
1098  SCIP* scip, /**< SCIP data structure */
1099  SCIP_CONSDATA* consdata, /**< linear constraint data */
1100  FILE* file /**< output file (or NULL for standard output) */
1101  )
1102 {
1103  assert(scip != NULL);
1104  assert(consdata != NULL);
1105 
1106  /* print left hand side for ranged rows */
1107  if( !SCIPisInfinity(scip, -consdata->lhs)
1108  && !SCIPisInfinity(scip, consdata->rhs)
1109  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1110  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1111 
1112  /* print coefficients and variables */
1113  if( consdata->nvars == 0 )
1114  SCIPinfoMessage(scip, file, "0");
1115  else
1116  {
1117  /* post linear sum of the linear constraint */
1118  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1119  }
1120 
1121  /* print right hand side */
1122  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1123  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1124  else if( !SCIPisInfinity(scip, consdata->rhs) )
1125  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1126  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1127  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1128  else
1129  SCIPinfoMessage(scip, file, " [free]");
1130 
1131  return SCIP_OKAY;
1132 }
1133 
1134 /** prints linear constraint and contained solution values of variables to file stream */
1135 static
1137  SCIP* scip, /**< SCIP data structure */
1138  SCIP_CONS* cons, /**< linear constraint */
1139  SCIP_SOL* sol, /**< solution to print */
1140  FILE* file /**< output file (or NULL for standard output) */
1141  )
1142 {
1143  SCIP_CONSDATA* consdata;
1144 
1145  assert(scip != NULL);
1146  assert(cons != NULL);
1147 
1148  consdata = SCIPconsGetData(cons);
1149  assert(consdata != NULL);
1150 
1152 
1153  /* print left hand side for ranged rows */
1154  if( !SCIPisInfinity(scip, -consdata->lhs)
1155  && !SCIPisInfinity(scip, consdata->rhs)
1156  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1157  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1158 
1159  /* print coefficients and variables */
1160  if( consdata->nvars == 0 )
1161  SCIPinfoMessage(scip, file, "0");
1162  else
1163  {
1164  int v;
1165 
1166  /* post linear sum of the linear constraint */
1167  for( v = 0; v < consdata->nvars; ++v )
1168  {
1169  if( consdata->vals != NULL )
1170  {
1171  if( consdata->vals[v] == 1.0 )
1172  {
1173  if( v > 0 )
1174  SCIPinfoMessage(scip, file, " +");
1175  }
1176  else if( consdata->vals[v] == -1.0 )
1177  SCIPinfoMessage(scip, file, " -");
1178  else
1179  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1180  }
1181  else if( consdata->nvars > 0 )
1182  SCIPinfoMessage(scip, file, " +");
1183 
1184  /* print variable name */
1185  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1186 
1187  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1188  }
1189  }
1190 
1191  /* print right hand side */
1192  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1193  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1194  else if( !SCIPisInfinity(scip, consdata->rhs) )
1195  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1196  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1197  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1198  else
1199  SCIPinfoMessage(scip, file, " [free]");
1200 
1201  SCIPinfoMessage(scip, file, ";\n");
1202 
1203  return SCIP_OKAY;
1204 }
1205 
1206 /** invalidates activity bounds, such that they are recalculated in next get */
1207 static
1209  SCIP_CONSDATA* consdata /**< linear constraint */
1210  )
1211 {
1212  assert(consdata != NULL);
1213 
1214  consdata->validactivities = FALSE;
1215  consdata->validminact = FALSE;
1216  consdata->validmaxact = FALSE;
1217  consdata->validglbminact = FALSE;
1218  consdata->validglbmaxact = FALSE;
1219  consdata->validmaxabsval = FALSE;
1220  consdata->validminabsval = FALSE;
1221  consdata->hasnonbinvalid = FALSE;
1222  consdata->minactivity = SCIP_INVALID;
1223  consdata->maxactivity = SCIP_INVALID;
1224  consdata->lastminactivity = SCIP_INVALID;
1225  consdata->lastmaxactivity = SCIP_INVALID;
1226  consdata->maxabsval = SCIP_INVALID;
1227  consdata->minabsval = SCIP_INVALID;
1228  consdata->maxactdelta = SCIP_INVALID;
1229  consdata->maxactdeltavar = NULL;
1230  consdata->minactivityneginf = -1;
1231  consdata->minactivityposinf = -1;
1232  consdata->maxactivityneginf = -1;
1233  consdata->maxactivityposinf = -1;
1234  consdata->minactivityneghuge = -1;
1235  consdata->minactivityposhuge = -1;
1236  consdata->maxactivityneghuge = -1;
1237  consdata->maxactivityposhuge = -1;
1238  consdata->glbminactivity = SCIP_INVALID;
1239  consdata->glbmaxactivity = SCIP_INVALID;
1240  consdata->lastglbminactivity = SCIP_INVALID;
1241  consdata->lastglbmaxactivity = SCIP_INVALID;
1242  consdata->glbminactivityneginf = -1;
1243  consdata->glbminactivityposinf = -1;
1244  consdata->glbmaxactivityneginf = -1;
1245  consdata->glbmaxactivityposinf = -1;
1246  consdata->glbminactivityneghuge = -1;
1247  consdata->glbminactivityposhuge = -1;
1248  consdata->glbmaxactivityneghuge = -1;
1249  consdata->glbmaxactivityposhuge = -1;
1250 }
1251 
1252 /** compute the pseudo activity of a constraint */
1253 static
1255  SCIP* scip, /**< SCIP data structure */
1256  SCIP_CONSDATA* consdata /**< linear constraint data */
1257  )
1258 {
1259  int i;
1260  int pseudoactivityposinf;
1261  int pseudoactivityneginf;
1262  SCIP_Real pseudoactivity;
1263  SCIP_Real bound;
1264  SCIP_Real val;
1265 
1266  pseudoactivity = 0;
1267  pseudoactivityposinf = 0;
1268  pseudoactivityneginf = 0;
1269 
1270  for( i = consdata->nvars - 1; i >= 0; --i )
1271  {
1272  val = consdata->vals[i];
1273  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1274  if( SCIPisInfinity(scip, bound) )
1275  {
1276  if( val > 0.0 )
1277  pseudoactivityposinf++;
1278  else
1279  pseudoactivityneginf++;
1280  }
1281  else
1282  {
1283  if( SCIPisInfinity(scip, -bound) )
1284  {
1285  if( val > 0.0 )
1286  pseudoactivityneginf++;
1287  else
1288  pseudoactivityposinf++;
1289  }
1290  else
1291  pseudoactivity += val * bound;
1292  }
1293  }
1294 
1295  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1296  return SCIP_INVALID;
1297  else if( pseudoactivityneginf > 0 )
1298  return -SCIPinfinity(scip);
1299  else if( pseudoactivityposinf > 0 )
1300  return SCIPinfinity(scip);
1301 
1302  return pseudoactivity;
1303 }
1304 
1305 /** recompute the minactivity of a constraint */
1306 static
1308  SCIP* scip, /**< SCIP data structure */
1309  SCIP_CONSDATA* consdata /**< linear constraint data */
1310  )
1311 {
1312  int i;
1313  SCIP_Real bound;
1314 
1315  consdata->minactivity = 0;
1316 
1317  for( i = consdata->nvars - 1; i >= 0; --i )
1318  {
1319  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1320  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1321  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1322  consdata->minactivity += consdata->vals[i] * bound;
1323  }
1324 
1325  /* the activity was just computed from scratch and is valid now */
1326  consdata->validminact = TRUE;
1327 
1328  /* the activity was just computed from scratch, mark it to be reliable */
1329  consdata->lastminactivity = consdata->minactivity;
1330 }
1331 
1332 /** recompute the maxactivity of a constraint */
1333 static
1335  SCIP* scip, /**< SCIP data structure */
1336  SCIP_CONSDATA* consdata /**< linear constraint data */
1337  )
1338 {
1339  int i;
1340  SCIP_Real bound;
1341 
1342  consdata->maxactivity = 0;
1343 
1344  for( i = consdata->nvars - 1; i >= 0; --i )
1345  {
1346  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1347  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1348  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1349  consdata->maxactivity += consdata->vals[i] * bound;
1350  }
1351 
1352  /* the activity was just computed from scratch and is valid now */
1353  consdata->validmaxact = TRUE;
1354 
1355  /* the activity was just computed from scratch, mark it to be reliable */
1356  consdata->lastmaxactivity = consdata->maxactivity;
1357 }
1358 
1359 /** recompute the global minactivity of a constraint */
1360 static
1362  SCIP* scip, /**< SCIP data structure */
1363  SCIP_CONSDATA* consdata /**< linear constraint data */
1364  )
1365 {
1366  int i;
1367  SCIP_Real bound;
1368 
1369  consdata->glbminactivity = 0;
1370 
1371  for( i = consdata->nvars - 1; i >= 0; --i )
1372  {
1373  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1374  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1375  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1376  consdata->glbminactivity += consdata->vals[i] * bound;
1377  }
1378 
1379  /* the activity was just computed from scratch and is valid now */
1380  consdata->validglbminact = TRUE;
1381 
1382  /* the activity was just computed from scratch, mark it to be reliable */
1383  consdata->lastglbminactivity = consdata->glbminactivity;
1384 }
1385 
1386 /** recompute the global maxactivity of a constraint */
1387 static
1389  SCIP* scip, /**< SCIP data structure */
1390  SCIP_CONSDATA* consdata /**< linear constraint data */
1391  )
1392 {
1393  int i;
1394  SCIP_Real bound;
1395 
1396  consdata->glbmaxactivity = 0;
1397 
1398  for( i = consdata->nvars - 1; i >= 0; --i )
1399  {
1400  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1401  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1402  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1403  consdata->glbmaxactivity += consdata->vals[i] * bound;
1404  }
1405 
1406  /* the activity was just computed from scratch and is valid now */
1407  consdata->validglbmaxact = TRUE;
1408 
1409  /* the activity was just computed from scratch, mark it to be reliable */
1410  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1411 }
1412 
1413 /** calculates maximum absolute value of coefficients */
1414 static
1416  SCIP_CONSDATA* consdata /**< linear constraint data */
1417  )
1418 {
1419  SCIP_Real absval;
1420  int i;
1421 
1422  assert(consdata != NULL);
1423  assert(!consdata->validmaxabsval);
1424  assert(consdata->maxabsval >= SCIP_INVALID);
1425 
1426  consdata->validmaxabsval = TRUE;
1427  consdata->maxabsval = 0.0;
1428  for( i = 0; i < consdata->nvars; ++i )
1429  {
1430  absval = consdata->vals[i];
1431  absval = REALABS(absval);
1432  if( absval > consdata->maxabsval )
1433  consdata->maxabsval = absval;
1434  }
1435 }
1436 
1437 /** calculates minimum absolute value of coefficients */
1438 static
1440  SCIP_CONSDATA* consdata /**< linear constraint data */
1441  )
1442 {
1443  SCIP_Real absval;
1444  int i;
1445 
1446  assert(consdata != NULL);
1447  assert(!consdata->validminabsval);
1448  assert(consdata->minabsval >= SCIP_INVALID);
1449 
1450  consdata->validminabsval = TRUE;
1451 
1452  if( consdata->nvars > 0 )
1453  consdata->minabsval = REALABS(consdata->vals[0]);
1454  else
1455  consdata->minabsval = 0.0;
1456 
1457  for( i = 1; i < consdata->nvars; ++i )
1458  {
1459  absval = consdata->vals[i];
1460  absval = REALABS(absval);
1461  if( absval < consdata->minabsval )
1462  consdata->minabsval = absval;
1463  }
1464 }
1465 
1466 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1467 static
1469  SCIP_CONSDATA* consdata /**< linear constraint data */
1470  )
1471 {
1472  int v;
1473 
1474  assert(!consdata->hasnonbinvalid);
1475  consdata->hasnonbinvar = FALSE;
1476  consdata->hascontvar = FALSE;
1477 
1478  for( v = consdata->nvars - 1; v >= 0; --v )
1479  {
1480  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1481 
1482  if( vartype != SCIP_VARTYPE_BINARY )
1483  {
1484  consdata->hasnonbinvar = TRUE;
1485 
1486  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1487  {
1488  consdata->hascontvar = TRUE;
1489  break;
1490  }
1491  }
1492  }
1493  assert(consdata->hascontvar || v < 0);
1494 
1495  consdata->hasnonbinvalid = TRUE;
1496 }
1497 
1498 
1499 #ifdef CHECKMAXACTDELTA
1500 /** checks that the stored maximal activity delta (if not invalid) is correct */
1501 static
1503  SCIP* scip, /**< SCIP data structure */
1504  SCIP_CONSDATA* consdata /**< linear constraint data */
1505  )
1506 {
1507  if( consdata->maxactdelta != SCIP_INVALID )
1508  {
1509  SCIP_Real maxactdelta = 0.0;
1510  SCIP_Real domain;
1511  SCIP_Real delta;
1512  SCIP_Real lb;
1513  SCIP_Real ub;
1514  int v;
1515 
1516  for( v = consdata->nvars - 1; v >= 0; --v )
1517  {
1518  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1519  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1520 
1521  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1522  {
1523  maxactdelta = SCIPinfinity(scip);
1524  break;
1525  }
1526 
1527  domain = ub - lb;
1528  delta = REALABS(consdata->vals[v]) * domain;
1529 
1530  if( delta > maxactdelta )
1531  {
1532  maxactdelta = delta;
1533  }
1534  }
1535  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1536  }
1537 }
1538 #else
1539 #define checkMaxActivityDelta(scip, consdata) /**/
1540 #endif
1541 
1542 /** recompute maximal activity contribution for a single variable */
1543 static
1545  SCIP* scip, /**< SCIP data structure */
1546  SCIP_CONSDATA* consdata /**< linear constraint data */
1547  )
1548 {
1549  SCIP_Real delta;
1550  int v;
1551 
1552  consdata->maxactdelta = 0.0;
1553 
1554  if( !consdata->hasnonbinvalid )
1555  consdataCheckNonbinvar(consdata);
1556 
1557  /* easy case, the problem consists only of binary variables */
1558  if( !consdata->hasnonbinvar )
1559  {
1560  for( v = consdata->nvars - 1; v >= 0; --v )
1561  {
1562  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1563  {
1564  delta = REALABS(consdata->vals[v]);
1565 
1566  if( delta > consdata->maxactdelta )
1567  {
1568  consdata->maxactdelta = delta;
1569  consdata->maxactdeltavar = consdata->vars[v];
1570  }
1571  }
1572  }
1573  return;
1574  }
1575 
1576  for( v = consdata->nvars - 1; v >= 0; --v )
1577  {
1578  SCIP_Real domain;
1579  SCIP_Real lb;
1580  SCIP_Real ub;
1581 
1582  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1583  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1584 
1585  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1586  {
1587  consdata->maxactdelta = SCIPinfinity(scip);
1588  consdata->maxactdeltavar = consdata->vars[v];
1589  break;
1590  }
1591 
1592  domain = ub - lb;
1593  delta = REALABS(consdata->vals[v]) * domain;
1594 
1595  if( delta > consdata->maxactdelta )
1596  {
1597  consdata->maxactdelta = delta;
1598  consdata->maxactdeltavar = consdata->vars[v];
1599  }
1600  }
1601 }
1602 
1603 
1604 /** updates activities for a change in a bound */
1605 static
1607  SCIP* scip, /**< SCIP data structure */
1608  SCIP_CONSDATA* consdata, /**< linear constraint data */
1609  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1610  SCIP_Real oldbound, /**< old bound of variable */
1611  SCIP_Real newbound, /**< new bound of variable */
1612  SCIP_Real val, /**< coefficient of constraint entry */
1613  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1614  SCIP_Bool global, /**< is it a global or a local bound change? */
1615  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1616  )
1617 {
1618  SCIP_Real* activity;
1619  SCIP_Real* lastactivity;
1620  int* activityposinf;
1621  int* activityneginf;
1622  int* activityposhuge;
1623  int* activityneghuge;
1624  SCIP_Real oldcontribution;
1625  SCIP_Real newcontribution;
1626  SCIP_Real delta;
1627  SCIP_Bool validact;
1628  SCIP_Bool finitenewbound;
1629  SCIP_Bool hugevalnewcont;
1630 
1631  assert(scip != NULL);
1632  assert(consdata != NULL);
1633  assert(global || (var != NULL));
1634  assert(consdata->validactivities);
1635  assert(consdata->minactivity < SCIP_INVALID);
1636  assert(consdata->maxactivity < SCIP_INVALID);
1637  assert(consdata->lastminactivity < SCIP_INVALID);
1638  assert(consdata->lastmaxactivity < SCIP_INVALID);
1639  assert(consdata->minactivityneginf >= 0);
1640  assert(consdata->minactivityposinf >= 0);
1641  assert(consdata->maxactivityneginf >= 0);
1642  assert(consdata->maxactivityposinf >= 0);
1643  assert(consdata->minactivityneghuge >= 0);
1644  assert(consdata->minactivityposhuge >= 0);
1645  assert(consdata->maxactivityneghuge >= 0);
1646  assert(consdata->maxactivityposhuge >= 0);
1647  assert(consdata->glbminactivity < SCIP_INVALID);
1648  assert(consdata->glbmaxactivity < SCIP_INVALID);
1649  assert(consdata->lastglbminactivity < SCIP_INVALID);
1650  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1651  assert(consdata->glbminactivityneginf >= 0);
1652  assert(consdata->glbminactivityposinf >= 0);
1653  assert(consdata->glbmaxactivityneginf >= 0);
1654  assert(consdata->glbmaxactivityposinf >= 0);
1655  assert(consdata->glbminactivityneghuge >= 0);
1656  assert(consdata->glbminactivityposhuge >= 0);
1657  assert(consdata->glbmaxactivityneghuge >= 0);
1658  assert(consdata->glbmaxactivityposhuge >= 0);
1659 
1660  delta = 0.0;
1661 
1662  /* we are updating global activities */
1663  if( global )
1664  {
1665  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1666  * lower bound + pos. coef: update minactivity
1667  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1668  * upper bound + pos. coef: update maxactivity
1669  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1670  */
1671  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1672  {
1673  if( val > 0.0 )
1674  {
1675  activity = &(consdata->glbminactivity);
1676  lastactivity = &(consdata->lastglbminactivity);
1677  activityposinf = &(consdata->glbminactivityposinf);
1678  activityneginf = &(consdata->glbminactivityneginf);
1679  activityposhuge = &(consdata->glbminactivityposhuge);
1680  activityneghuge = &(consdata->glbminactivityneghuge);
1681  validact = consdata->validglbminact;
1682  }
1683  else
1684  {
1685  activity = &(consdata->glbmaxactivity);
1686  lastactivity = &(consdata->lastglbmaxactivity);
1687  activityposinf = &(consdata->glbmaxactivityneginf);
1688  activityneginf = &(consdata->glbmaxactivityposinf);
1689  activityposhuge = &(consdata->glbmaxactivityposhuge);
1690  activityneghuge = &(consdata->glbmaxactivityneghuge);
1691  validact = consdata->validglbmaxact;
1692  }
1693  }
1694  else
1695  {
1696  if( val > 0.0 )
1697  {
1698  activity = &(consdata->glbmaxactivity);
1699  lastactivity = &(consdata->lastglbmaxactivity);
1700  activityposinf = &(consdata->glbmaxactivityposinf);
1701  activityneginf = &(consdata->glbmaxactivityneginf);
1702  activityposhuge = &(consdata->glbmaxactivityposhuge);
1703  activityneghuge = &(consdata->glbmaxactivityneghuge);
1704  validact = consdata->validglbmaxact;
1705  }
1706  else
1707  {
1708  activity = &(consdata->glbminactivity);
1709  lastactivity = &(consdata->lastglbminactivity);
1710  activityposinf = &(consdata->glbminactivityneginf);
1711  activityneginf = &(consdata->glbminactivityposinf);
1712  activityposhuge = &(consdata->glbminactivityposhuge);
1713  activityneghuge = &(consdata->glbminactivityneghuge);
1714  validact = consdata->validglbminact;
1715  }
1716  }
1717  }
1718  /* we are updating local activities */
1719  else
1720  {
1721  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1722  * lower bound + pos. coef: update minactivity
1723  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1724  * upper bound + pos. coef: update maxactivity
1725  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1726  */
1727  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1728  {
1729  if( val > 0.0 )
1730  {
1731  activity = &(consdata->minactivity);
1732  lastactivity = &(consdata->lastminactivity);
1733  activityposinf = &(consdata->minactivityposinf);
1734  activityneginf = &(consdata->minactivityneginf);
1735  activityposhuge = &(consdata->minactivityposhuge);
1736  activityneghuge = &(consdata->minactivityneghuge);
1737  validact = consdata->validminact;
1738  }
1739  else
1740  {
1741  activity = &(consdata->maxactivity);
1742  lastactivity = &(consdata->lastmaxactivity);
1743  activityposinf = &(consdata->maxactivityneginf);
1744  activityneginf = &(consdata->maxactivityposinf);
1745  activityposhuge = &(consdata->maxactivityposhuge);
1746  activityneghuge = &(consdata->maxactivityneghuge);
1747  validact = consdata->validmaxact;
1748  }
1749  }
1750  else
1751  {
1752  if( val > 0.0 )
1753  {
1754  activity = &(consdata->maxactivity);
1755  lastactivity = &(consdata->lastmaxactivity);
1756  activityposinf = &(consdata->maxactivityposinf);
1757  activityneginf = &(consdata->maxactivityneginf);
1758  activityposhuge = &(consdata->maxactivityposhuge);
1759  activityneghuge = &(consdata->maxactivityneghuge);
1760  validact = consdata->validmaxact;
1761  }
1762  else
1763  {
1764  activity = &(consdata->minactivity);
1765  lastactivity = &(consdata->lastminactivity);
1766  activityposinf = &(consdata->minactivityneginf);
1767  activityneginf = &(consdata->minactivityposinf);
1768  activityposhuge = &(consdata->minactivityposhuge);
1769  activityneghuge = &(consdata->minactivityneghuge);
1770  validact = consdata->validminact;
1771  }
1772  }
1773  }
1774 
1775  oldcontribution = val * oldbound;
1776  newcontribution = val * newbound;
1777  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1778  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1779 
1780  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1781  {
1782  /* old bound was +infinity */
1783  if( oldbound > 0.0 )
1784  {
1785  assert((*activityposinf) >= 1);
1786 
1787  /* we only have to do something if the new bound is not again +infinity */
1788  if( finitenewbound || newbound < 0.0 )
1789  {
1790  /* decrease the counter for positive infinite contributions */
1791  (*activityposinf)--;
1792 
1793  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1794  if( !finitenewbound && newbound < 0.0 )
1795  (*activityneginf)++;
1796  else if( hugevalnewcont )
1797  {
1798  /* if the contribution of this variable is too large, increase the counter for huge values */
1799  if( newcontribution > 0.0 )
1800  (*activityposhuge)++;
1801  else
1802  (*activityneghuge)++;
1803  }
1804  /* "normal case": just add the contribution to the activity */
1805  else
1806  delta = newcontribution;
1807  }
1808  }
1809  /* old bound was -infinity */
1810  else
1811  {
1812  assert(oldbound < 0.0);
1813  assert((*activityneginf) >= 1);
1814 
1815  /* we only have to do something ig the new bound is not again -infinity */
1816  if( finitenewbound || newbound > 0.0 )
1817  {
1818  /* decrease the counter for negative infinite contributions */
1819  (*activityneginf)--;
1820 
1821  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1822  if( !finitenewbound && newbound > 0.0 )
1823  (*activityposinf)++;
1824  else if( hugevalnewcont )
1825  {
1826  /* if the contribution of this variable is too large, increase the counter for huge values */
1827  if( newcontribution > 0.0 )
1828  (*activityposhuge)++;
1829  else
1830  (*activityneghuge)++;
1831  }
1832  /* "normal case": just add the contribution to the activity */
1833  else
1834  delta = newcontribution;
1835  }
1836  }
1837  }
1838  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1839  {
1840  /* old contribution was too large and positive */
1841  if( oldcontribution > 0.0 )
1842  {
1843  assert((*activityposhuge) >= 1);
1844 
1845  /* decrease the counter for huge positive contributions; it might be increased again later,
1846  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1847  */
1848  (*activityposhuge)--;
1849 
1850  if( !finitenewbound )
1851  {
1852  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1853  if( newbound > 0.0 )
1854  (*activityposinf)++;
1855  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1856  else
1857  (*activityneginf)++;
1858  }
1859  else if( hugevalnewcont )
1860  {
1861  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1862  if( newcontribution > 0.0 )
1863  (*activityposhuge)++;
1864  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1865  else
1866  (*activityneghuge)++;
1867  }
1868  /* "normal case": just add the contribution to the activity */
1869  else
1870  delta = newcontribution;
1871  }
1872  /* old contribution was too large and negative */
1873  else
1874  {
1875  assert(oldcontribution < 0.0);
1876  assert((*activityneghuge) >= 1);
1877 
1878  /* decrease the counter for huge negative contributions; it might be increased again later,
1879  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1880  */
1881  (*activityneghuge)--;
1882 
1883  if( !finitenewbound )
1884  {
1885  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1886  if( newbound > 0.0 )
1887  (*activityposinf)++;
1888  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1889  else
1890  (*activityneginf)++;
1891  }
1892  else if( hugevalnewcont )
1893  {
1894  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1895  if( newcontribution > 0.0 )
1896  (*activityposhuge)++;
1897  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1898  else
1899  (*activityneghuge)++;
1900  }
1901  /* "normal case": just add the contribution to the activity */
1902  else
1903  delta = newcontribution;
1904  }
1905  }
1906  /* old bound was finite and not too large */
1907  else
1908  {
1909  if( !finitenewbound )
1910  {
1911  /* if the new bound is +infinity, the old contribution has to be subtracted
1912  * and the counter for positive infinite contributions has to be increased
1913  */
1914  if( newbound > 0.0 )
1915  {
1916  (*activityposinf)++;
1917  delta = -oldcontribution;
1918  }
1919  /* if the new bound is -infinity, the old contribution has to be subtracted
1920  * and the counter for negative infinite contributions has to be increased
1921  */
1922  else
1923  {
1924  assert(newbound < 0.0 );
1925 
1926  (*activityneginf)++;
1927  delta = -oldcontribution;
1928  }
1929  }
1930  /* if the contribution of this variable is too large, increase the counter for huge values */
1931  else if( hugevalnewcont )
1932  {
1933  if( newcontribution > 0.0 )
1934  {
1935  (*activityposhuge)++;
1936  delta = -oldcontribution;
1937  }
1938  else
1939  {
1940  (*activityneghuge)++;
1941  delta = -oldcontribution;
1942  }
1943  }
1944  /* "normal case": just update the activity */
1945  else
1946  delta = newcontribution - oldcontribution;
1947  }
1948 
1949  /* update the activity, if the current value is valid and there was a change in the finite part */
1950  if( validact && (delta != 0.0) )
1951  {
1952  /* if the absolute value of the activity is increased, this is regarded as reliable,
1953  * otherwise, we check whether we can still trust the updated value
1954  */
1955  (*activity) = (*activity) + delta;
1956  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1957 
1958  if( REALABS((*lastactivity)) < REALABS(*activity) )
1959  {
1960  (*lastactivity) = (*activity);
1961  }
1962  else
1963  {
1964  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1965  {
1966  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1967  (global ? "global " : ""), (*activity));
1968 
1969  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1970  if( global )
1971  {
1972  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1973  consdata->validglbminact = FALSE;
1974  else
1975  consdata->validglbmaxact = FALSE;
1976  }
1977  else
1978  {
1979  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1980  consdata->validminact = FALSE;
1981  else
1982  consdata->validmaxact = FALSE;
1983  }
1984  }
1985  }
1986  }
1987 }
1988 
1989 /** updates minimum and maximum activity for a change in lower 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 oldlb, /**< old lower bound of variable */
1996  SCIP_Real newlb, /**< new lower 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, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2008 
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 activity for a change in upper bound */
2015 static
2017  SCIP* scip, /**< SCIP data structure */
2018  SCIP_CONSDATA* consdata, /**< linear constraint data */
2019  SCIP_VAR* var, /**< variable that has been changed */
2020  SCIP_Real oldub, /**< old upper bound of variable */
2021  SCIP_Real newub, /**< new upper bound of variable */
2022  SCIP_Real val, /**< coefficient of constraint entry */
2023  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2024  )
2025 {
2026  assert(scip != NULL);
2027  assert(consdata != NULL);
2028  assert(var != NULL);
2029 
2030  if( consdata->validactivities )
2031  {
2032  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2033 
2034  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
2035  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
2036  }
2037 }
2038 
2039 /** updates minimum and maximum global activity for a change in the global lower bound */
2040 static
2042  SCIP* scip, /**< SCIP data structure */
2043  SCIP_CONSDATA* consdata, /**< linear constraint data */
2044  SCIP_Real oldlb, /**< old lower bound of variable */
2045  SCIP_Real newlb, /**< new lower bound of variable */
2046  SCIP_Real val, /**< coefficient of constraint entry */
2047  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2048  )
2049 {
2050  assert(scip != NULL);
2051  assert(consdata != NULL);
2052 
2053  if( consdata->validactivities )
2054  {
2055  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2056 
2057  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2058  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2059  }
2061 
2062 /** updates minimum and maximum global activity for a change in global upper bound */
2063 static
2065  SCIP* scip, /**< SCIP data structure */
2066  SCIP_CONSDATA* consdata, /**< linear constraint data */
2067  SCIP_Real oldub, /**< old upper bound of variable */
2068  SCIP_Real newub, /**< new upper bound of variable */
2069  SCIP_Real val, /**< coefficient of constraint entry */
2070  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2071  )
2072 {
2073  assert(scip != NULL);
2074  assert(consdata != NULL);
2075 
2076  if( consdata->validactivities )
2077  {
2078  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2079 
2080  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2081  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2082  }
2084 
2085 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2086 static
2088  SCIP* scip, /**< SCIP data structure */
2089  SCIP_CONSDATA* consdata, /**< linear constraint data */
2090  SCIP_VAR* var, /**< variable of constraint entry */
2091  SCIP_Real val, /**< coefficient of constraint entry */
2092  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2093  )
2094 {
2095  assert(scip != NULL);
2096  assert(consdata != NULL);
2097  assert(var != NULL);
2098 
2099  /* update maximum absolute value */
2100  if( consdata->validmaxabsval )
2101  {
2102  SCIP_Real absval;
2103 
2104  assert(consdata->maxabsval < SCIP_INVALID);
2105 
2106  absval = REALABS(val);
2107  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2108  }
2109 
2110  if( consdata->validminabsval )
2111  {
2112  SCIP_Real absval;
2113 
2114  assert(consdata->minabsval < SCIP_INVALID);
2115 
2116  absval = REALABS(val);
2117  consdata->minabsval = MIN(consdata->minabsval, absval);
2118  }
2119 
2120  /* update minimal and maximal activity */
2121  if( consdata->validactivities )
2122  {
2123  assert(consdata->minactivity < SCIP_INVALID);
2124  assert(consdata->maxactivity < SCIP_INVALID);
2125  assert(consdata->glbminactivity < SCIP_INVALID);
2126  assert(consdata->glbmaxactivity < SCIP_INVALID);
2127 
2128  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2129  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2130  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2131  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2132  }
2133 }
2134 
2135 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2136 static
2138  SCIP* scip, /**< SCIP data structure */
2139  SCIP_CONSDATA* consdata, /**< linear constraint data */
2140  SCIP_VAR* var, /**< variable of constraint entry */
2141  SCIP_Real val, /**< coefficient of constraint entry */
2142  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2143  )
2144 {
2145  assert(scip != NULL);
2146  assert(consdata != NULL);
2147  assert(var != NULL);
2148 
2149  /* invalidate maximum absolute value, if this coefficient was the maximum */
2150  if( consdata->validmaxabsval )
2151  {
2152  SCIP_Real absval;
2153 
2154  absval = REALABS(val);
2155 
2156  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2157  {
2158  consdata->validmaxabsval = FALSE;
2159  consdata->maxabsval = SCIP_INVALID;
2160  }
2161  }
2162 
2163  /* invalidate minimum absolute value, if this coefficient was the minimum */
2164  if( consdata->validminabsval )
2165  {
2166  SCIP_Real absval;
2167 
2168  absval = REALABS(val);
2169 
2170  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2171  {
2172  consdata->validminabsval = FALSE;
2173  consdata->minabsval = SCIP_INVALID;
2174  }
2175  }
2176 
2177  /* update minimal and maximal activity */
2178  if( consdata->validactivities )
2179  {
2180  assert(consdata->minactivity < SCIP_INVALID);
2181  assert(consdata->maxactivity < SCIP_INVALID);
2182  assert(consdata->glbminactivity < SCIP_INVALID);
2183  assert(consdata->glbmaxactivity < SCIP_INVALID);
2184 
2185  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2186  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2187  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2188  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2189  }
2190 }
2191 
2192 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2193 static
2195  SCIP* scip, /**< SCIP data structure */
2196  SCIP_CONSDATA* consdata, /**< linear constraint data */
2197  SCIP_VAR* var, /**< variable of constraint entry */
2198  SCIP_Real oldval, /**< old coefficient of constraint entry */
2199  SCIP_Real newval, /**< new coefficient of constraint entry */
2200  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2201  )
2202 {
2203  assert(scip != NULL);
2204  assert(consdata != NULL);
2205  assert(var != NULL);
2206 
2207  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2208  assert(!SCIPisZero(scip, oldval));
2209 
2210  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2211  assert(!SCIPisZero(scip, newval));
2212 
2213  /* update maximum absolute value */
2214  if( consdata->validmaxabsval )
2215  {
2216  SCIP_Real absval;
2217 
2218  absval = REALABS(newval);
2219 
2220  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2221  {
2222  consdata->maxabsval = absval;
2223  }
2224  else
2225  {
2226  absval = REALABS(oldval);
2227 
2228  /* invalidate maximum absolute value */
2229  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2230  {
2231  consdata->validmaxabsval = FALSE;
2232  consdata->maxabsval = SCIP_INVALID;
2233  }
2234  }
2235  }
2236 
2237  /* update minimum absolute value */
2238  if( consdata->validminabsval )
2239  {
2240  SCIP_Real absval;
2241 
2242  absval = REALABS(newval);
2243 
2244  if( SCIPisLE(scip, absval, consdata->minabsval) )
2245  {
2246  consdata->minabsval = absval;
2247  }
2248  else
2249  {
2250  absval = REALABS(oldval);
2251 
2252  /* invalidate minimum absolute value */
2253  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2254  {
2255  consdata->validminabsval = FALSE;
2256  consdata->minabsval = SCIP_INVALID;
2257  }
2258  }
2259  }
2260 
2261  /* update maximum activity delta */
2262  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2263  {
2264  SCIP_Real domain;
2265  SCIP_Real delta;
2266 
2267  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2268  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2269 
2270  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2271  delta = REALABS(newval) * domain;
2272 
2273  if( delta > consdata->maxactdelta )
2274  {
2275  consdata->maxactdelta = delta;
2276  consdata->maxactdeltavar = var;
2277  }
2278  else
2279  {
2280  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2281  if( consdata->maxactdeltavar == var )
2282  consdata->maxactdelta = SCIP_INVALID;
2283  }
2284  }
2285 
2286  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2287  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2288  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2289 }
2290 
2291 /** returns the maximum absolute value of all coefficients in the constraint */
2292 static
2294  SCIP_CONSDATA* consdata /**< linear constraint data */
2295  )
2296 {
2297  assert(consdata != NULL);
2298 
2299  if( !consdata->validmaxabsval )
2300  consdataCalcMaxAbsval(consdata);
2301  assert(consdata->validmaxabsval);
2302  assert(consdata->maxabsval < SCIP_INVALID);
2303 
2304  return consdata->maxabsval;
2305 }
2306 
2307 /** returns the minimum absolute value of all coefficients in the constraint */
2308 static
2310  SCIP_CONSDATA* consdata /**< linear constraint data */
2311  )
2313  assert(consdata != NULL);
2314 
2315  if( !consdata->validminabsval )
2316  consdataCalcMinAbsval(consdata);
2317  assert(consdata->validminabsval);
2318  assert(consdata->minabsval < SCIP_INVALID);
2319 
2320  return consdata->minabsval;
2321 }
2322 
2323 /** calculates minimum and maximum local and global activity for constraint from scratch;
2324  * additionally recalculates maximum absolute value of coefficients
2325  */
2326 static
2328  SCIP* scip, /**< SCIP data structure */
2329  SCIP_CONSDATA* consdata /**< linear constraint data */
2330  )
2331 {
2332  int i;
2333 
2334  assert(scip != NULL);
2335  assert(consdata != NULL);
2336  assert(!consdata->validactivities);
2337  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2338  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2339  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2340  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2341 
2342  consdata->validmaxabsval = TRUE;
2343  consdata->validminabsval = TRUE;
2344  consdata->validactivities = TRUE;
2345  consdata->validminact = TRUE;
2346  consdata->validmaxact = TRUE;
2347  consdata->validglbminact = TRUE;
2348  consdata->validglbmaxact = TRUE;
2349  consdata->maxabsval = 0.0;
2350  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2351  consdata->minactivity = 0.0;
2352  consdata->maxactivity = 0.0;
2353  consdata->lastminactivity = 0.0;
2354  consdata->lastmaxactivity = 0.0;
2355  consdata->minactivityneginf = 0;
2356  consdata->minactivityposinf = 0;
2357  consdata->maxactivityneginf = 0;
2358  consdata->maxactivityposinf = 0;
2359  consdata->minactivityneghuge = 0;
2360  consdata->minactivityposhuge = 0;
2361  consdata->maxactivityneghuge = 0;
2362  consdata->maxactivityposhuge = 0;
2363  consdata->glbminactivity = 0.0;
2364  consdata->glbmaxactivity = 0.0;
2365  consdata->lastglbminactivity = 0.0;
2366  consdata->lastglbmaxactivity = 0.0;
2367  consdata->glbminactivityneginf = 0;
2368  consdata->glbminactivityposinf = 0;
2369  consdata->glbmaxactivityneginf = 0;
2370  consdata->glbmaxactivityposinf = 0;
2371  consdata->glbminactivityneghuge = 0;
2372  consdata->glbminactivityposhuge = 0;
2373  consdata->glbmaxactivityneghuge = 0;
2374  consdata->glbmaxactivityposhuge = 0;
2375 
2376  for( i = 0; i < consdata->nvars; ++i )
2377  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2378 
2379  consdata->lastminactivity = consdata->minactivity;
2380  consdata->lastmaxactivity = consdata->maxactivity;
2381  consdata->lastglbminactivity = consdata->glbminactivity;
2382  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2383 }
2384 
2385 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2386  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2387  */
2388 static
2389 void getMinActivity(
2390  SCIP* scip, /**< SCIP data structure */
2391  SCIP_CONSDATA* consdata, /**< linear constraint */
2392  int posinf, /**< number of coefficients contributing pos. infinite value */
2393  int neginf, /**< number of coefficients contributing neg. infinite value */
2394  int poshuge, /**< number of coefficients contributing huge pos. value */
2395  int neghuge, /**< number of coefficients contributing huge neg. value */
2396  SCIP_Real delta, /**< value to subtract from stored minactivity
2397  * (contribution of the variable set to zero when getting residual activity) */
2398  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2399  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2400  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2401  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2402  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2403  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2404  )
2405 {
2406  assert(scip != NULL);
2407  assert(consdata != NULL);
2408  assert(posinf >= 0);
2409  assert(neginf >= 0);
2410  assert(poshuge >= 0);
2411  assert(neghuge >= 0);
2412  assert(minactivity != NULL);
2413  assert(isrelax != NULL);
2414  assert(issettoinfinity != NULL);
2415 
2416  /* if we have pos. infinite contributions, the minactivity is +infty */
2417  if( posinf > 0 )
2418  {
2419  *minactivity = SCIPinfinity(scip);
2420  *issettoinfinity = TRUE;
2421  *isrelax = FALSE;
2422  }
2423  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2424  else if( neginf > 0 )
2425  {
2426  *minactivity = -SCIPinfinity(scip);
2427  *issettoinfinity = TRUE;
2428  *isrelax = FALSE;
2429  }
2430  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2431  else if( neghuge > 0 )
2432  {
2433  *minactivity = -SCIPinfinity(scip);
2434  *issettoinfinity = TRUE;
2435  *isrelax = TRUE;
2436  }
2437  /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2438  else if( !goodrelax && poshuge > 0 )
2439  {
2440  *minactivity = -SCIPinfinity(scip);
2441  *issettoinfinity = TRUE;
2442  *isrelax = TRUE;
2443  }
2444  else
2445  {
2446  SCIP_Real tmpactivity;
2447 
2448  /* recompute minactivity if it is not valid */
2449  if( global )
2450  {
2451  if( !consdata->validglbminact )
2452  consdataRecomputeGlbMinactivity(scip, consdata);
2453  assert(consdata->validglbminact);
2454 
2455  tmpactivity = consdata->glbminactivity;
2456  }
2457  else
2458  {
2459  if( !consdata->validminact )
2460  consdataRecomputeMinactivity(scip, consdata);
2461  assert(consdata->validminact);
2462 
2463  tmpactivity = consdata->minactivity;
2464  }
2465 
2466  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2467  * a feasible relaxation of the minactivity is the number of positive huge contributions
2468  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2469  */
2470  if( poshuge > 0 )
2471  {
2472  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2473  *issettoinfinity = FALSE;
2474  *isrelax = TRUE;
2475  }
2476  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2477  else
2478  {
2479  *minactivity = tmpactivity - delta;
2480  *issettoinfinity = FALSE;
2481  *isrelax = FALSE;
2482  }
2483  }
2484 }
2485 
2486 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2487  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2488  */
2489 static
2490 void getMaxActivity(
2491  SCIP* scip, /**< SCIP data structure */
2492  SCIP_CONSDATA* consdata, /**< linear constraint */
2493  int posinf, /**< number of coefficients contributing pos. infinite value */
2494  int neginf, /**< number of coefficients contributing neg. infinite value */
2495  int poshuge, /**< number of coefficients contributing huge pos. value */
2496  int neghuge, /**< number of coefficients contributing huge neg. value */
2497  SCIP_Real delta, /**< value to subtract from stored maxactivity
2498  * (contribution of the variable set to zero when getting residual activity) */
2499  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2500  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2501  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2502  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2503  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2504  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2505  )
2506 {
2507  assert(scip != NULL);
2508  assert(consdata != NULL);
2509  assert(posinf >= 0);
2510  assert(neginf >= 0);
2511  assert(poshuge >= 0);
2512  assert(neghuge >= 0);
2513  assert(maxactivity != NULL);
2514  assert(isrelax != NULL);
2515  assert(issettoinfinity != NULL);
2516 
2517  /* if we have neg. infinite contributions, the maxactivity is -infty */
2518  if( neginf > 0 )
2519  {
2520  *maxactivity = -SCIPinfinity(scip);
2521  *issettoinfinity = TRUE;
2522  *isrelax = FALSE;
2523  }
2524  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2525  else if( posinf > 0 )
2526  {
2527  *maxactivity = SCIPinfinity(scip);
2528  *issettoinfinity = TRUE;
2529  *isrelax = FALSE;
2530  }
2531  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2532  else if( poshuge > 0 )
2533  {
2534  *maxactivity = SCIPinfinity(scip);
2535  *issettoinfinity = TRUE;
2536  *isrelax = TRUE;
2537  }
2538  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2539  else if( !goodrelax && neghuge > 0 )
2540  {
2541  *maxactivity = SCIPinfinity(scip);
2542  *issettoinfinity = TRUE;
2543  *isrelax = TRUE;
2544  }
2545  else
2546  {
2547  SCIP_Real tmpactivity;
2548 
2549  /* recompute maxactivity if it is not valid */
2550  if( global )
2551  {
2552  if( !consdata->validglbmaxact )
2553  consdataRecomputeGlbMaxactivity(scip, consdata);
2554  assert(consdata->validglbmaxact);
2555 
2556  tmpactivity = consdata->glbmaxactivity;
2557  }
2558  else
2559  {
2560  if( !consdata->validmaxact )
2561  consdataRecomputeMaxactivity(scip, consdata);
2562  assert(consdata->validmaxact);
2563 
2564  tmpactivity = consdata->maxactivity;
2565  }
2566 
2567  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2568  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2569  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2570  */
2571  if( neghuge > 0 )
2572  {
2573  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2574  *issettoinfinity = FALSE;
2575  *isrelax = TRUE;
2576  }
2577  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2578  else
2579  {
2580  *maxactivity = tmpactivity - delta;
2581  *issettoinfinity = FALSE;
2582  *isrelax = FALSE;
2583  }
2584  }
2585 }
2586 
2587 /** gets activity bounds for constraint */
2588 static
2590  SCIP* scip, /**< SCIP data structure */
2591  SCIP_CONSDATA* consdata, /**< linear constraint */
2592  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2593  * relaxed activities ignored, anyway? */
2594  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2595  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2596  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2597  * i.e. <= the exact minactivity (in case of huge contributions),
2598  * or equal to the exact minimal activity */
2599  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2600  * i.e. >= the exact maxactivity (in case of huge contributions),
2601  * or equal to the exact maximal activity */
2602  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2603  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2604 
2605  )
2606 {
2607  assert(scip != NULL);
2608  assert(consdata != NULL);
2609  assert(minactivity != NULL);
2610  assert(maxactivity != NULL);
2611  assert(isminsettoinfinity != NULL);
2612  assert(ismaxsettoinfinity != NULL);
2613 
2614  if( !consdata->validactivities )
2615  {
2616  consdataCalcActivities(scip, consdata);
2617  assert(consdata->validminact);
2618  assert(consdata->validmaxact);
2619  }
2620  assert(consdata->minactivity < SCIP_INVALID);
2621  assert(consdata->maxactivity < SCIP_INVALID);
2622  assert(consdata->minactivityneginf >= 0);
2623  assert(consdata->minactivityposinf >= 0);
2624  assert(consdata->maxactivityneginf >= 0);
2625  assert(consdata->maxactivityposinf >= 0);
2626 
2627  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2628  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2629  minactivity, minisrelax, isminsettoinfinity);
2630 
2631  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2632  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2633  maxactivity, maxisrelax, ismaxsettoinfinity);
2634 }
2635 
2636 /** calculates activity bounds for constraint after setting variable to zero */
2637 static
2639  SCIP* scip, /**< SCIP data structure */
2640  SCIP_CONSDATA* consdata, /**< linear constraint */
2641  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2642  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2643  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2644  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2645  )
2646 {
2647  SCIP_VAR* var;
2648  SCIP_Real val;
2649  SCIP_Real lb;
2650  SCIP_Real ub;
2651  int v;
2652 
2653  assert(scip != NULL);
2654  assert(consdata != NULL);
2655  assert(cancelvar != NULL);
2656  assert(resactivity != NULL);
2658  *resactivity = 0.0;
2659 
2660  for( v = 0; v < consdata->nvars; ++v )
2661  {
2662  var = consdata->vars[v];
2663  assert(var != NULL);
2664  if( var == cancelvar )
2665  continue;
2666 
2667  val = consdata->vals[v];
2668 
2669  if( useglobalbounds )
2670  {
2671  lb = SCIPvarGetLbGlobal(var);
2672  ub = SCIPvarGetUbGlobal(var);
2673  }
2674  else
2675  {
2676  lb = SCIPvarGetLbLocal(var);
2677  ub = SCIPvarGetUbLocal(var);
2678  }
2679 
2680  assert(!SCIPisZero(scip, val));
2681  assert(SCIPisLE(scip, lb, ub));
2682 
2683  if( val > 0.0 )
2684  {
2685  if( isminresact )
2686  {
2687  assert(!SCIPisInfinity(scip, -lb));
2688  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2689  *resactivity += val*lb;
2690  }
2691  else
2692  {
2693  assert(!SCIPisInfinity(scip, ub));
2694  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2695  *resactivity += val*ub;
2696  }
2697  }
2698  else
2699  {
2700  if( isminresact)
2701  {
2702  assert(!SCIPisInfinity(scip, ub));
2703  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2704  *resactivity += val*ub;
2705  }
2706  else
2707  {
2708  assert(!SCIPisInfinity(scip, -lb));
2709  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2710  *resactivity += val*lb;
2711  }
2712  }
2713  }
2714  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2715 }
2716 
2717 /** gets activity bounds for constraint after setting variable to zero */
2718 static
2720  SCIP* scip, /**< SCIP data structure */
2721  SCIP_CONSDATA* consdata, /**< linear constraint */
2722  SCIP_VAR* var, /**< variable to calculate activity residual for */
2723  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2724  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2725  * relaxed acticities ignored, anyway? */
2726  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2727  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2728  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2729  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2730  * contributions), or equal to the exact residual minactivity */
2731  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2732  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2733  * contributions), or equal to the exact residual minactivity */
2734  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2735  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2736  )
2737 {
2738  SCIP_Real minactbound;
2739  SCIP_Real maxactbound;
2740  SCIP_Real absval;
2741 
2742  assert(scip != NULL);
2743  assert(consdata != NULL);
2744  assert(var != NULL);
2745  assert(minresactivity != NULL);
2746  assert(maxresactivity != NULL);
2747  assert(minisrelax != NULL);
2748  assert(maxisrelax != NULL);
2749  assert(isminsettoinfinity != NULL);
2750  assert(ismaxsettoinfinity != NULL);
2751 
2752  /* get activity bounds of linear constraint */
2753  if( !consdata->validactivities )
2754  {
2755  consdataCalcActivities(scip, consdata);
2756  assert(consdata->validminact);
2757  assert(consdata->validmaxact);
2758  }
2759  assert(consdata->minactivity < SCIP_INVALID);
2760  assert(consdata->maxactivity < SCIP_INVALID);
2761  assert(consdata->minactivityneginf >= 0);
2762  assert(consdata->minactivityposinf >= 0);
2763  assert(consdata->maxactivityneginf >= 0);
2764  assert(consdata->maxactivityposinf >= 0);
2765  assert(consdata->minactivityneghuge >= 0);
2766  assert(consdata->minactivityposhuge >= 0);
2767  assert(consdata->maxactivityneghuge >= 0);
2768  assert(consdata->maxactivityposhuge >= 0);
2769 
2770  if( val > 0.0 )
2771  {
2772  minactbound = SCIPvarGetLbLocal(var);
2773  maxactbound = SCIPvarGetUbLocal(var);
2774  absval = val;
2775  }
2776  else
2777  {
2778  minactbound = -SCIPvarGetUbLocal(var);
2779  maxactbound = -SCIPvarGetLbLocal(var);
2780  absval = -val;
2781  }
2782 
2783  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2784  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2785  */
2786  if( SCIPisInfinity(scip, minactbound) )
2787  {
2788  assert(consdata->minactivityposinf >= 1);
2789 
2790  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2791  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2792  minresactivity, minisrelax, isminsettoinfinity);
2793  }
2794  else if( SCIPisInfinity(scip, -minactbound) )
2795  {
2796  assert(consdata->minactivityneginf >= 1);
2797 
2798  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2799  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2800  minresactivity, minisrelax, isminsettoinfinity);
2801  }
2802  else if( SCIPisHugeValue(scip, minactbound * absval) )
2803  {
2804  assert(consdata->minactivityposhuge >= 1);
2805 
2806  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2807  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2808  minresactivity, minisrelax, isminsettoinfinity);
2809  }
2810  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2811  {
2812  assert(consdata->minactivityneghuge >= 1);
2813 
2814  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2815  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2816  minresactivity, minisrelax, isminsettoinfinity);
2817  }
2818  else
2819  {
2820  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2821  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2822  minresactivity, minisrelax, isminsettoinfinity);
2823  }
2824 
2825  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2826  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2827  */
2828  if( SCIPisInfinity(scip, -maxactbound) )
2829  {
2830  assert(consdata->maxactivityneginf >= 1);
2831 
2832  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2833  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2834  maxresactivity, maxisrelax, ismaxsettoinfinity);
2835  }
2836  else if( SCIPisInfinity(scip, maxactbound) )
2837  {
2838  assert(consdata->maxactivityposinf >= 1);
2839 
2840  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2841  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2842  maxresactivity, maxisrelax, ismaxsettoinfinity);
2843  }
2844  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2845  {
2846  assert(consdata->maxactivityposhuge >= 1);
2847 
2848  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2849  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2850  maxresactivity, maxisrelax, ismaxsettoinfinity);
2851  }
2852  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2853  {
2854  assert(consdata->maxactivityneghuge >= 1);
2855 
2856  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2857  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2858  maxresactivity, maxisrelax, ismaxsettoinfinity);
2859  }
2860  else
2861  {
2862  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2863  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2864  maxresactivity, maxisrelax, ismaxsettoinfinity);
2865  }
2866 }
2867 
2868 /** gets global activity bounds for constraint */
2869 static
2871  SCIP* scip, /**< SCIP data structure */
2872  SCIP_CONSDATA* consdata, /**< linear constraint */
2873  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2874  * relaxed acticities ignored, anyway? */
2875  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2876  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2877  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2878  * i.e. <= the exact minactivity (in case of huge contributions),
2879  * or equal to the exact minimal activity */
2880  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2881  * i.e. >= the exact maxactivity (in case of huge contributions),
2882  * or equal to the exact maximal activity */
2883  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2884  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2885  )
2886 {
2887  assert(scip != NULL);
2888  assert(consdata != NULL);
2889  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2890  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2891 
2892  if( !consdata->validactivities )
2893  {
2894  consdataCalcActivities(scip, consdata);
2895  assert(consdata->validglbminact);
2896  assert(consdata->validglbmaxact);
2897  }
2898  assert(consdata->glbminactivity < SCIP_INVALID);
2899  assert(consdata->glbmaxactivity < SCIP_INVALID);
2900  assert(consdata->glbminactivityneginf >= 0);
2901  assert(consdata->glbminactivityposinf >= 0);
2902  assert(consdata->glbmaxactivityneginf >= 0);
2903  assert(consdata->glbmaxactivityposinf >= 0);
2904  assert(consdata->glbminactivityneghuge >= 0);
2905  assert(consdata->glbminactivityposhuge >= 0);
2906  assert(consdata->glbmaxactivityneghuge >= 0);
2907  assert(consdata->glbmaxactivityposhuge >= 0);
2908 
2909  if( glbminactivity != NULL )
2910  {
2911  assert(isminsettoinfinity != NULL);
2912  assert(minisrelax != NULL);
2913 
2914  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2915  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2916  glbminactivity, minisrelax, isminsettoinfinity);
2917  }
2918 
2919  if( glbmaxactivity != NULL )
2920  {
2921  assert(ismaxsettoinfinity != NULL);
2922  assert(maxisrelax != NULL);
2923 
2924  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2925  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2926  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2927  }
2928 }
2929 
2930 /** gets global activity bounds for constraint after setting variable to zero */
2931 static
2933  SCIP* scip, /**< SCIP data structure */
2934  SCIP_CONSDATA* consdata, /**< linear constraint */
2935  SCIP_VAR* var, /**< variable to calculate activity residual for */
2936  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2937  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2938  * relaxed acticities ignored, anyway? */
2939  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2940  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2941  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2942  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2943  * contributions), or equal to the exact residual minactivity */
2944  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2945  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2946  * contributions), or equal to the exact residual minactivity */
2947  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2948  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2949  )
2950 {
2951  SCIP_Real minactbound;
2952  SCIP_Real maxactbound;
2953  SCIP_Real absval;
2954 
2955  assert(scip != NULL);
2956  assert(consdata != NULL);
2957  assert(var != NULL);
2958  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2959  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2960 
2961  /* get activity bounds of linear constraint */
2962  if( !consdata->validactivities )
2963  consdataCalcActivities(scip, consdata);
2964 
2965  assert(consdata->glbminactivity < SCIP_INVALID);
2966  assert(consdata->glbmaxactivity < SCIP_INVALID);
2967  assert(consdata->glbminactivityneginf >= 0);
2968  assert(consdata->glbminactivityposinf >= 0);
2969  assert(consdata->glbmaxactivityneginf >= 0);
2970  assert(consdata->glbmaxactivityposinf >= 0);
2971 
2972  if( val > 0.0 )
2973  {
2974  minactbound = SCIPvarGetLbGlobal(var);
2975  maxactbound = SCIPvarGetUbGlobal(var);
2976  absval = val;
2977  }
2978  else
2979  {
2980  minactbound = -SCIPvarGetUbGlobal(var);
2981  maxactbound = -SCIPvarGetLbGlobal(var);
2982  absval = -val;
2983  }
2984 
2985  if( minresactivity != NULL )
2986  {
2987  assert(isminsettoinfinity != NULL);
2988  assert(minisrelax != NULL);
2989 
2990  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2991  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2992  */
2993  if( SCIPisInfinity(scip, minactbound) )
2994  {
2995  assert(consdata->glbminactivityposinf >= 1);
2996 
2997  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2998  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2999  minresactivity, minisrelax, isminsettoinfinity);
3000  }
3001  else if( SCIPisInfinity(scip, -minactbound) )
3002  {
3003  assert(consdata->glbminactivityneginf >= 1);
3004 
3005  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
3006  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3007  minresactivity, minisrelax, isminsettoinfinity);
3008  }
3009  else if( SCIPisHugeValue(scip, minactbound * absval) )
3010  {
3011  assert(consdata->glbminactivityposhuge >= 1);
3012 
3013  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3014  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3015  minresactivity, minisrelax, isminsettoinfinity);
3016  }
3017  else if( SCIPisHugeValue(scip, -minactbound * absval) )
3018  {
3019  assert(consdata->glbminactivityneghuge >= 1);
3020 
3021  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3022  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3023  minresactivity, minisrelax, isminsettoinfinity);
3024  }
3025  else
3026  {
3027  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3028  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3029  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3030  }
3031  }
3032 
3033  if( maxresactivity != NULL )
3034  {
3035  assert(ismaxsettoinfinity != NULL);
3036  assert(maxisrelax != NULL);
3037 
3038  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3039  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3040  */
3041  if( SCIPisInfinity(scip, -maxactbound) )
3042  {
3043  assert(consdata->glbmaxactivityneginf >= 1);
3044 
3045  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3046  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3047  maxresactivity, maxisrelax, ismaxsettoinfinity);
3048  }
3049  else if( SCIPisInfinity(scip, maxactbound) )
3050  {
3051  assert(consdata->glbmaxactivityposinf >= 1);
3052 
3053  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3054  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3055  maxresactivity, maxisrelax, ismaxsettoinfinity);
3056  }
3057  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3058  {
3059  assert(consdata->glbmaxactivityposhuge >= 1);
3060 
3061  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3062  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3063  maxresactivity, maxisrelax, ismaxsettoinfinity);
3064  }
3065  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3066  {
3067  assert(consdata->glbmaxactivityneghuge >= 1);
3068 
3069  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3070  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3071  maxresactivity, maxisrelax, ismaxsettoinfinity);
3072  }
3073  else
3074  {
3075  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3076  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3077  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3078  }
3079  }
3080 }
3081 
3082 /** calculates the activity of the linear constraint for given solution */
3083 static
3085  SCIP* scip, /**< SCIP data structure */
3086  SCIP_CONSDATA* consdata, /**< linear constraint data */
3087  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3088  )
3089 {
3090  SCIP_Real activity;
3091 
3092  assert(scip != NULL);
3093  assert(consdata != NULL);
3094 
3095  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3096  activity = consdataComputePseudoActivity(scip, consdata);
3097  else
3098  {
3099  SCIP_Real solval;
3100  int nposinf;
3101  int nneginf;
3102  SCIP_Bool negsign;
3103  int v;
3104 
3105  activity = 0.0;
3106  nposinf = 0;
3107  nneginf = 0;
3108 
3109  for( v = 0; v < consdata->nvars; ++v )
3110  {
3111  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3112 
3113  if( consdata->vals[v] < 0 )
3114  negsign = TRUE;
3115  else
3116  negsign = FALSE;
3117 
3118  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3119  ++nposinf;
3120  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3121  ++nneginf;
3122  else
3123  activity += consdata->vals[v] * solval;
3124  }
3125  assert(nneginf >= 0 && nposinf >= 0);
3126 
3127  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3128 
3129  /* check for amount of infinity values and correct the activity */
3130  if( nposinf > 0 && nneginf > 0 )
3131  activity = (consdata->rhs + consdata->lhs) / 2;
3132  else if( nposinf > 0 )
3133  activity = SCIPinfinity(scip);
3134  else if( nneginf > 0 )
3135  activity = -SCIPinfinity(scip);
3136 
3137  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3138  }
3139 
3140  if( activity == SCIP_INVALID ) /*lint !e777*/
3141  return activity;
3142  else if( activity < 0 )
3143  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3144  else
3145  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3146 
3147  return activity;
3148 }
3149 
3150 /** calculates the feasibility of the linear constraint for given solution */
3151 static
3153  SCIP* scip, /**< SCIP data structure */
3154  SCIP_CONSDATA* consdata, /**< linear constraint data */
3155  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3156  )
3157 {
3158  SCIP_Real activity;
3159 
3160  assert(scip != NULL);
3161  assert(consdata != NULL);
3162 
3163  activity = consdataGetActivity(scip, consdata, sol);
3164 
3165  if( activity == SCIP_INVALID ) /*lint !e777*/
3166  return -SCIPinfinity(scip);
3167 
3168  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3169 }
3170 
3171 /** updates bit signatures after adding a single coefficient */
3172 static
3174  SCIP_CONSDATA* consdata, /**< linear constraint data */
3175  int pos /**< position of coefficient to update signatures for */
3176  )
3177 {
3178  uint64_t varsignature;
3179  SCIP_Real lb;
3180  SCIP_Real ub;
3181  SCIP_Real val;
3182 
3183  assert(consdata != NULL);
3184  assert(consdata->validsignature);
3185 
3186  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3187  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3188  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3189  val = consdata->vals[pos];
3190  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3191  consdata->possignature |= varsignature;
3192  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3193  consdata->negsignature |= varsignature;
3194 }
3195 
3196 /** calculates the bit signatures of the given constraint data */
3197 static
3199  SCIP_CONSDATA* consdata /**< linear constraint data */
3200  )
3201 {
3202  assert(consdata != NULL);
3203 
3204  if( !consdata->validsignature )
3205  {
3206  int i;
3207 
3208  consdata->validsignature = TRUE;
3209  consdata->possignature = 0;
3210  consdata->negsignature = 0;
3211  for( i = 0; i < consdata->nvars; ++i )
3212  consdataUpdateSignatures(consdata, i);
3213  }
3214 }
3215 
3216 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3217 static
3218 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3219 { /*lint --e{715}*/
3220  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3221  SCIP_VAR* var1;
3222  SCIP_VAR* var2;
3223 
3224  assert(consdata != NULL);
3225  assert(0 <= ind1 && ind1 < consdata->nvars);
3226  assert(0 <= ind2 && ind2 < consdata->nvars);
3227 
3228  var1 = consdata->vars[ind1];
3229  var2 = consdata->vars[ind2];
3230 
3231  /* exactly one variable is binary */
3232  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3233  {
3234  return (SCIPvarIsBinary(var1) ? -1 : +1);
3235  }
3236  /* both variables are binary */
3237  else if( SCIPvarIsBinary(var1) )
3238  {
3239  return SCIPvarCompare(var1, var2);
3240  }
3241  else
3242  {
3243  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3244  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3245 
3246  if( vartype1 < vartype2 )
3247  return -1;
3248  else if( vartype1 > vartype2 )
3249  return +1;
3250  else
3251  return SCIPvarCompare(var1, var2);
3252  }
3253 }
3254 
3255 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3256 static
3257 SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3258 { /*lint --e{715}*/
3259  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3260  SCIP_VAR* var1;
3261  SCIP_VAR* var2;
3262 
3263  assert(consdata != NULL);
3264  assert(0 <= ind1 && ind1 < consdata->nvars);
3265  assert(0 <= ind2 && ind2 < consdata->nvars);
3266 
3267  var1 = consdata->vars[ind1];
3268  var2 = consdata->vars[ind2];
3269 
3270  /* exactly one variable is binary */
3271  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3272  {
3273  return (SCIPvarIsBinary(var1) ? -1 : +1);
3274  }
3275  /* both variables are binary */
3276  else if( SCIPvarIsBinary(var1) )
3277  {
3278  SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3279  SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3280 
3281  if( EPSGT(abscoef1, abscoef2, 1e-9) )
3282  return -1;
3283  else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3284  return +1;
3285  else
3286  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3287  }
3288  else
3289  {
3290  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3291  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3292 
3293  if( vartype1 < vartype2 )
3294  {
3295  return -1;
3296  }
3297  else if( vartype1 > vartype2 )
3298  {
3299  return +1;
3300  }
3301  else
3302  {
3303  /* both variables are continuous */
3304  if( !SCIPvarIsIntegral(var1) )
3305  {
3306  assert(!SCIPvarIsIntegral(var2));
3307  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3308  }
3309  else
3310  {
3311  SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3312  SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3313 
3314  if( EPSGT(abscont1, abscont2, 1e-9) )
3315  return -1;
3316  else if( EPSGT(abscont2, abscont1, 1e-9) )
3317  return +1;
3318  else
3319  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3320  }
3321  }
3322  }
3323 }
3324 
3325 /** permutes the constraint's variables according to a given permutation. */
3326 static
3327 void permSortConsdata(
3328  SCIP_CONSDATA* consdata, /**< the constraint data */
3329  int* perm, /**< the target permutation */
3330  int nvars /**< the number of variables */
3331  )
3332 { /*lint --e{715}*/
3333  SCIP_VAR* varv;
3334  SCIP_EVENTDATA* eventdatav;
3335  SCIP_Real valv;
3336  int v;
3337  int i;
3338  int nexti;
3339 
3340  assert(perm != NULL);
3341  assert(consdata != NULL);
3342 
3343  /* permute the variables in the linear constraint according to the target permutation */
3344  eventdatav = NULL;
3345  for( v = 0; v < nvars; ++v )
3346  {
3347  if( perm[v] != v )
3348  {
3349  varv = consdata->vars[v];
3350  valv = consdata->vals[v];
3351  if( consdata->eventdata != NULL )
3352  eventdatav = consdata->eventdata[v];
3353  i = v;
3354  do
3355  {
3356  assert(0 <= perm[i] && perm[i] < nvars);
3357  assert(perm[i] != i);
3358  consdata->vars[i] = consdata->vars[perm[i]];
3359  consdata->vals[i] = consdata->vals[perm[i]];
3360  if( consdata->eventdata != NULL )
3361  {
3362  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3363  consdata->eventdata[i]->varpos = i;
3364  }
3365  nexti = perm[i];
3366  perm[i] = i;
3367  i = nexti;
3368  }
3369  while( perm[i] != v );
3370  consdata->vars[i] = varv;
3371  consdata->vals[i] = valv;
3372  if( consdata->eventdata != NULL )
3373  {
3374  consdata->eventdata[i] = eventdatav;
3375  consdata->eventdata[i]->varpos = i;
3376  }
3377  perm[i] = i;
3378  }
3379  }
3380 #ifdef SCIP_DEBUG
3381  /* check sorting */
3382  for( v = 0; v < nvars; ++v )
3383  {
3384  assert(perm[v] == v);
3385  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3386  }
3387 #endif
3388 }
3389 
3390 /** sorts linear constraint's variables depending on the stage of the solving process:
3391  * - during PRESOLVING
3392  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3393  * and the variables of the same type by non-decreasing variable index
3394  *
3395  * - during SOLVING
3396  * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3397  * and binary and integer variables by their global max activity delta (within each group),
3398  * ties within a group are broken by problem index of the variable.
3399  *
3400  * This fastens the propagation time of the constraint handler.
3401  */
3402 static
3404  SCIP* scip, /**< SCIP data structure */
3405  SCIP_CONSDATA* consdata /**< linear constraint data */
3406  )
3407 {
3408  assert(scip != NULL);
3409  assert(consdata != NULL);
3410 
3411  /* check if there are variables for sorting */
3412  if( consdata->nvars <= 1 )
3413  {
3414  consdata->indexsorted = TRUE;
3415  consdata->coefsorted = TRUE;
3416  consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3417  }
3418  else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3419  || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3420  {
3421  int* perm;
3422  int v;
3423 
3424  /* get temporary memory to store the sorted permutation */
3425  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3426 
3427  /* call sorting method */
3428  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3429  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3430  else
3431  SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3432 
3433  permSortConsdata(consdata, perm, consdata->nvars);
3434 
3435  /* free temporary memory */
3436  SCIPfreeBufferArray(scip, &perm);
3437 
3438  if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE )
3439  {
3440  consdata->indexsorted = FALSE;
3441  consdata->coefsorted = TRUE;
3442 
3443  /* count binary variables in the sorted vars array */
3444  consdata->nbinvars = 0;
3445  for( v = 0; v < consdata->nvars; ++v )
3446  {
3447  if( SCIPvarIsBinary(consdata->vars[v]) )
3448  ++consdata->nbinvars;
3449  else
3450  break;
3451  }
3452  }
3453  else
3454  {
3455  consdata->indexsorted = TRUE;
3456  consdata->coefsorted = FALSE;
3457  }
3458  }
3459 
3460  return SCIP_OKAY;
3461 }
3462 
3463 
3464 /*
3465  * local linear constraint handler methods
3466  */
3467 
3468 /** sets left hand side of linear constraint */
3469 static
3471  SCIP* scip, /**< SCIP data structure */
3472  SCIP_CONS* cons, /**< linear constraint */
3473  SCIP_Real lhs /**< new left hand side */
3474  )
3475 {
3476  SCIP_CONSDATA* consdata;
3477  SCIP_Bool locked;
3478  int i;
3479 
3480  assert(scip != NULL);
3481  assert(cons != NULL);
3482  assert(!SCIPisInfinity(scip, lhs));
3483 
3484  /* adjust value to not be smaller than -inf */
3485  if ( SCIPisInfinity(scip, -lhs) )
3486  lhs = -SCIPinfinity(scip);
3487 
3488  consdata = SCIPconsGetData(cons);
3489  assert(consdata != NULL);
3490  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3491  assert(!SCIPisInfinity(scip, consdata->lhs));
3492 
3493  /* check whether the side is not changed */
3494  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3495  return SCIP_OKAY;
3496 
3497  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3498  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3499  {
3500  consdata->rhs = lhs;
3501  assert(consdata->row == NULL);
3502  }
3503 
3504  locked = FALSE;
3505  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3506  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3507 
3508  /* if necessary, update the rounding locks of variables */
3509  if( locked )
3510  {
3511  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3512  {
3513  SCIP_VAR** vars;
3514  SCIP_Real* vals;
3515  int v;
3516 
3517  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3518  vars = consdata->vars;
3519  vals = consdata->vals;
3520 
3521  for( v = 0; v < consdata->nvars; ++v )
3522  {
3523  assert(vars[v] != NULL);
3524  assert(!SCIPisZero(scip, vals[v]));
3525 
3526  if( SCIPisPositive(scip, vals[v]) )
3527  {
3528  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3529  }
3530  else
3531  {
3532  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3533  }
3534  }
3535  }
3536  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3537  {
3538  SCIP_VAR** vars;
3539  SCIP_Real* vals;
3540  int v;
3541 
3542  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3543  vars = consdata->vars;
3544  vals = consdata->vals;
3545 
3546  for( v = 0; v < consdata->nvars; ++v )
3547  {
3548  assert(vars[v] != NULL);
3549  assert(!SCIPisZero(scip, vals[v]));
3550 
3551  if( SCIPisPositive(scip, vals[v]) )
3552  {
3553  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3554  }
3555  else
3556  {
3557  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3558  }
3559  }
3560  }
3561  }
3562 
3563  /* 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 */
3564  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3565  {
3566  consdata->boundstightened = 0;
3567  consdata->presolved = FALSE;
3568  consdata->cliquesadded = FALSE;
3569  consdata->implsadded = FALSE;
3570 
3571  /* mark the constraint for propagation */
3572  if( SCIPconsIsTransformed(cons) )
3573  {
3574  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3575  }
3576  }
3577 
3578  /* set new left hand side and update constraint data */
3579  consdata->lhs = lhs;
3580  consdata->changed = TRUE;
3581  consdata->normalized = FALSE;
3582  consdata->upgradetried = FALSE;
3583  consdata->rangedrowpropagated = 0;
3584 
3585  /* update the lhs of the LP row */
3586  if( consdata->row != NULL )
3587  {
3588  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3589  }
3590 
3591  return SCIP_OKAY;
3592 }
3593 
3594 /** sets right hand side of linear constraint */
3595 static
3597  SCIP* scip, /**< SCIP data structure */
3598  SCIP_CONS* cons, /**< linear constraint */
3599  SCIP_Real rhs /**< new right hand side */
3600  )
3601 {
3602  SCIP_CONSDATA* consdata;
3603  SCIP_Bool locked;
3604  int i;
3605 
3606  assert(scip != NULL);
3607  assert(cons != NULL);
3608  assert(!SCIPisInfinity(scip, -rhs));
3609 
3610  /* adjust value to not be larger than inf */
3611  if ( SCIPisInfinity(scip, rhs) )
3612  rhs = SCIPinfinity(scip);
3613 
3614  consdata = SCIPconsGetData(cons);
3615  assert(consdata != NULL);
3616  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3617  assert(!SCIPisInfinity(scip, -consdata->rhs));
3618 
3619  /* check whether the side is not changed */
3620  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3621  return SCIP_OKAY;
3622 
3623  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3624  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3625  {
3626  consdata->lhs = rhs;
3627  assert(consdata->row == NULL);
3628  }
3629 
3630  locked = FALSE;
3631  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3632  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3633 
3634  /* if necessary, update the rounding locks of variables */
3635  if( locked )
3636  {
3637  assert(SCIPconsIsTransformed(cons));
3638 
3639  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3640  {
3641  SCIP_VAR** vars;
3642  SCIP_Real* vals;
3643  int v;
3644 
3645  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3646  vars = consdata->vars;
3647  vals = consdata->vals;
3648 
3649  for( v = 0; v < consdata->nvars; ++v )
3650  {
3651  assert(vars[v] != NULL);
3652  assert(!SCIPisZero(scip, vals[v]));
3653 
3654  if( SCIPisPositive(scip, vals[v]) )
3655  {
3656  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3657  }
3658  else
3659  {
3660  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3661  }
3662  }
3663  }
3664  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3665  {
3666  SCIP_VAR** vars;
3667  SCIP_Real* vals;
3668  int v;
3669 
3670  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3671  vars = consdata->vars;
3672  vals = consdata->vals;
3673 
3674  for( v = 0; v < consdata->nvars; ++v )
3675  {
3676  assert(vars[v] != NULL);
3677  assert(!SCIPisZero(scip, vals[v]));
3678 
3679  if( SCIPisPositive(scip, vals[v]) )
3680  {
3681  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3682  }
3683  else
3684  {
3685  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3686  }
3687  }
3688  }
3689  }
3690 
3691  /* 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 */
3692  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3693  {
3694  consdata->boundstightened = 0;
3695  consdata->presolved = FALSE;
3696  consdata->cliquesadded = FALSE;
3697  consdata->implsadded = FALSE;
3698 
3699  /* mark the constraint for propagation */
3700  if( SCIPconsIsTransformed(cons) )
3701  {
3702  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3703  }
3704  }
3705 
3706  /* set new right hand side and update constraint data */
3707  consdata->rhs = rhs;
3708  consdata->changed = TRUE;
3709  consdata->normalized = FALSE;
3710  consdata->upgradetried = FALSE;
3711  consdata->rangedrowpropagated = 0;
3712 
3713  /* update the rhs of the LP row */
3714  if( consdata->row != NULL )
3715  {
3716  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3717  }
3718 
3719  return SCIP_OKAY;
3720 }
3721 
3722 /** adds coefficient in linear constraint */
3723 static
3725  SCIP* scip, /**< SCIP data structure */
3726  SCIP_CONS* cons, /**< linear constraint */
3727  SCIP_VAR* var, /**< variable of constraint entry */
3728  SCIP_Real val /**< coefficient of constraint entry */
3729  )
3730 {
3731  SCIP_CONSDATA* consdata;
3732  SCIP_Bool transformed;
3733 
3734  assert(scip != NULL);
3735  assert(cons != NULL);
3736  assert(var != NULL);
3737 
3738  /* relaxation-only variables must not be used in checked or enforced constraints */
3739  assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3740 
3741  /* ignore coefficient if it is nearly zero */
3742  if( SCIPisZero(scip, val) )
3743  return SCIP_OKAY;
3744 
3745  consdata = SCIPconsGetData(cons);
3746  assert(consdata != NULL);
3747 
3748  /* are we in the transformed problem? */
3749  transformed = SCIPconsIsTransformed(cons);
3750 
3751  /* always use transformed variables in transformed constraints */
3752  if( transformed )
3753  {
3754  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3755  }
3756  assert(var != NULL);
3757  assert(transformed == SCIPvarIsTransformed(var));
3758 
3759  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3760  consdata->vars[consdata->nvars] = var;
3761  consdata->vals[consdata->nvars] = val;
3762  consdata->nvars++;
3763 
3764  /* capture variable */
3765  SCIP_CALL( SCIPcaptureVar(scip, var) );
3766 
3767  /* if we are in transformed problem, the variable needs an additional event data */
3768  if( transformed )
3769  {
3770  if( consdata->eventdata != NULL )
3771  {
3772  SCIP_CONSHDLR* conshdlr;
3773  SCIP_CONSHDLRDATA* conshdlrdata;
3774 
3775  /* check for event handler */
3776  conshdlr = SCIPconsGetHdlr(cons);
3777  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3778  assert(conshdlrdata != NULL);
3779  assert(conshdlrdata->eventhdlr != NULL);
3780 
3781  /* initialize eventdata array */
3782  consdata->eventdata[consdata->nvars-1] = NULL;
3783 
3784  /* catch bound change events of variable */
3785  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3786  }
3787 
3788  /* update minimum and maximum activities */
3789  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3790 
3791  /* update maximum activity delta */
3792  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3793  {
3794  SCIP_Real lb;
3795  SCIP_Real ub;
3796 
3797  lb = SCIPvarGetLbLocal(var);
3798  ub = SCIPvarGetUbLocal(var);
3799 
3800  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3801  {
3802  consdata->maxactdelta = SCIPinfinity(scip);
3803  consdata->maxactdeltavar = var;
3804  }
3805  else
3806  {
3807  SCIP_Real domain = ub - lb;
3808  SCIP_Real delta = REALABS(val) * domain;
3809 
3810  if( delta > consdata->maxactdelta )
3811  {
3812  consdata->maxactdelta = delta;
3813  consdata->maxactdeltavar = var;
3814  }
3815  }
3816  }
3817  }
3818 
3819  /* install rounding locks for new variable */
3820  SCIP_CALL( lockRounding(scip, cons, var, val) );
3821 
3822  /* mark the constraint for propagation */
3823  if( transformed )
3824  {
3825  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3826  }
3827 
3828  consdata->boundstightened = 0;
3829  consdata->presolved = FALSE;
3830  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3831 
3832  if( consdata->validsignature )
3833  consdataUpdateSignatures(consdata, consdata->nvars-1);
3834 
3835  consdata->changed = TRUE;
3836  consdata->normalized = FALSE;
3837  consdata->upgradetried = FALSE;
3838  consdata->cliquesadded = FALSE;
3839  consdata->implsadded = FALSE;
3840  consdata->rangedrowpropagated = 0;
3841 
3842  if( consdata->nvars == 1 )
3843  {
3844  consdata->indexsorted = TRUE;
3845  consdata->coefsorted = TRUE;
3846  consdata->merged = TRUE;
3847  }
3848  else
3849  {
3850  consdata->merged = FALSE;
3851 
3852  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3853  {
3854  consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3855  consdata->coefsorted = FALSE;
3856  }
3857  else
3858  {
3859  consdata->indexsorted = FALSE;
3860  consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3861  }
3862  }
3863 
3864  /* update hascontvar and hasnonbinvar flags */
3865  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3866  {
3867  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3868 
3869  if( vartype != SCIP_VARTYPE_BINARY )
3870  {
3871  consdata->hasnonbinvar = TRUE;
3872 
3873  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3874  consdata->hascontvar = TRUE;
3875  }
3876  }
3877 
3878  /* add the new coefficient to the LP row */
3879  if( consdata->row != NULL )
3880  {
3881  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3882  }
3883 
3884  return SCIP_OKAY;
3885 }
3886 
3887 /** deletes coefficient at given position from linear constraint data */
3888 static
3890  SCIP* scip, /**< SCIP data structure */
3891  SCIP_CONS* cons, /**< linear constraint */
3892  int pos /**< position of coefficient to delete */
3893  )
3894 {
3895  SCIP_CONSDATA* consdata;
3896  SCIP_VAR* var;
3897  SCIP_Real val;
3898 
3899  assert(scip != NULL);
3900  assert(cons != NULL);
3901 
3902  consdata = SCIPconsGetData(cons);
3903  assert(consdata != NULL);
3904  assert(0 <= pos && pos < consdata->nvars);
3905 
3906  var = consdata->vars[pos];
3907  val = consdata->vals[pos];
3908  assert(var != NULL);
3909 
3910  /* remove rounding locks for deleted variable */
3911  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3912 
3913  /* if we are in transformed problem, delete the event data of the variable */
3914  if( SCIPconsIsTransformed(cons) )
3915  {
3916  SCIP_CONSHDLR* conshdlr;
3917  SCIP_CONSHDLRDATA* conshdlrdata;
3918 
3919  /* check for event handler */
3920  conshdlr = SCIPconsGetHdlr(cons);
3921  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3922  assert(conshdlrdata != NULL);
3923  assert(conshdlrdata->eventhdlr != NULL);
3924 
3925  /* drop bound change events of variable */
3926  if( consdata->eventdata != NULL )
3927  {
3928  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3929  assert(consdata->eventdata[pos] == NULL);
3930  }
3931  }
3932 
3933  /* move the last variable to the free slot */
3934  if( pos != consdata->nvars - 1 )
3935  {
3936  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3937  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3938 
3939  if( consdata->eventdata != NULL )
3940  {
3941  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3942  assert(consdata->eventdata[pos] != NULL);
3943  consdata->eventdata[pos]->varpos = pos;
3944  }
3945 
3946  consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3947  consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3948  }
3949  consdata->nvars--;
3950 
3951  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3952  * of the remaining variable, or give exactly 0.0)
3953  */
3954  if( consdata->nvars <= 1 )
3955  consdataInvalidateActivities(consdata);
3956  else
3957  {
3958  if( SCIPconsIsTransformed(cons) )
3959  {
3960  /* if we are in transformed problem, update minimum and maximum activities */
3961  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3962 
3963  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3964  * delta needs to be recalculated on the next real propagation
3965  */
3966  if( consdata->maxactdeltavar == var )
3967  {
3968  consdata->maxactdelta = SCIP_INVALID;
3969  consdata->maxactdeltavar = NULL;
3970  }
3971  }
3972  }
3973 
3974  /* mark the constraint for propagation */
3975  if( SCIPconsIsTransformed(cons) )
3976  {
3977  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3978  }
3979 
3980  consdata->boundstightened = 0;
3981  consdata->presolved = FALSE;
3982  consdata->validsignature = FALSE;
3983  consdata->changed = TRUE;
3984  consdata->normalized = FALSE;
3985  consdata->upgradetried = FALSE;
3986  consdata->cliquesadded = FALSE;
3987  consdata->implsadded = FALSE;
3988  consdata->rangedrowpropagated = 0;
3989 
3990  /* check if hasnonbinvar flag might be incorrect now */
3991  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3992  {
3993  consdata->hasnonbinvalid = FALSE;
3994  }
3995 
3996  /* delete coefficient from the LP row */
3997  if( consdata->row != NULL )
3998  {
3999  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
4000  }
4001 
4002  /* release variable */
4003  SCIP_CALL( SCIPreleaseVar(scip, &var) );
4004 
4005  return SCIP_OKAY;
4006 }
4007 
4008 /** changes coefficient value at given position of linear constraint data */
4009 static
4011  SCIP* scip, /**< SCIP data structure */
4012  SCIP_CONS* cons, /**< linear constraint */
4013  int pos, /**< position of coefficient to delete */
4014  SCIP_Real newval /**< new value of coefficient */
4015  )
4016 {
4017  SCIP_CONSDATA* consdata;
4018  SCIP_VAR* var;
4019  SCIP_Real val;
4020  SCIP_Bool locked;
4021  int i;
4022 
4023  assert(scip != NULL);
4024  assert(cons != NULL);
4025  assert(!SCIPisZero(scip, newval));
4026 
4027  consdata = SCIPconsGetData(cons);
4028  assert(consdata != NULL);
4029  assert(0 <= pos && pos < consdata->nvars);
4030  assert(!SCIPisZero(scip, newval));
4031 
4032  var = consdata->vars[pos];
4033  val = consdata->vals[pos];
4034  assert(var != NULL);
4035  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
4036 
4037  locked = FALSE;
4038  for( i = 0; i < NLOCKTYPES && !locked; i++ )
4039  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4040 
4041  /* if necessary, update the rounding locks of the variable */
4042  if( locked && newval * val < 0.0 )
4043  {
4044  assert(SCIPconsIsTransformed(cons));
4045 
4046  /* remove rounding locks for variable with old coefficient */
4047  SCIP_CALL( unlockRounding(scip, cons, var, val) );
4048 
4049  /* install rounding locks for variable with new coefficient */
4050  SCIP_CALL( lockRounding(scip, cons, var, newval) );
4051  }
4052 
4053  /* change the value */
4054  consdata->vals[pos] = newval;
4055 
4056  if( consdata->coefsorted )
4057  {
4058  if( pos > 0 )
4059  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4060  if( consdata->coefsorted && pos < consdata->nvars - 1 )
4061  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4062  }
4063 
4064  /* update minimum and maximum activities */
4065  if( SCIPconsIsTransformed(cons) )
4066  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4067 
4068  /* mark the constraint for propagation */
4069  if( SCIPconsIsTransformed(cons) )
4070  {
4071  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4072  }
4073 
4074  consdata->boundstightened = 0;
4075  consdata->presolved = FALSE;
4076  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4077  consdata->changed = TRUE;
4078  consdata->normalized = FALSE;
4079  consdata->upgradetried = FALSE;
4080  consdata->cliquesadded = FALSE;
4081  consdata->implsadded = FALSE;
4082  consdata->rangedrowpropagated = 0;
4083 
4084  return SCIP_OKAY;
4085 }
4086 
4087 /** scales a linear constraint with a constant scalar */
4088 static
4090  SCIP* scip, /**< SCIP data structure */
4091  SCIP_CONS* cons, /**< linear constraint to scale */
4092  SCIP_Real scalar /**< value to scale constraint with */
4093  )
4094 {
4095  SCIP_CONSDATA* consdata;
4096  SCIP_Real newval;
4097  SCIP_Real absscalar;
4098  int i;
4099 
4100  assert(scip != NULL);
4101  assert(cons != NULL);
4102 
4103  consdata = SCIPconsGetData(cons);
4104  assert(consdata != NULL);
4105  assert(consdata->row == NULL);
4106  assert(!SCIPisEQ(scip, scalar, 1.0));
4107 
4108  if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4109  || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4110  {
4111  SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4112  SCIPconsGetName(cons), scalar);
4113 
4114  return SCIP_OKAY;
4115  }
4116 
4117  /* scale the coefficients */
4118  for( i = consdata->nvars - 1; i >= 0; --i )
4119  {
4120  newval = scalar * consdata->vals[i];
4121 
4122  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4123  * flooring down our new value
4124  */
4125  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4126  newval = SCIPfeasFloor(scip, newval + 0.5);
4127 
4128  if( SCIPisZero(scip, newval) )
4129  {
4130  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4131  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4132  SCIP_CALL( delCoefPos(scip, cons, i) );
4133  }
4134  else
4135  consdata->vals[i] = newval;
4136  }
4137 
4138  /* scale the sides */
4139  if( scalar < 0.0 )
4140  {
4141  SCIP_Real lhs;
4142 
4143  lhs = consdata->lhs;
4144  consdata->lhs = -consdata->rhs;
4145  consdata->rhs = -lhs;
4146  }
4147  absscalar = REALABS(scalar);
4148  if( !SCIPisInfinity(scip, -consdata->lhs) )
4149  {
4150  newval = absscalar * consdata->lhs;
4151 
4152  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4153  * flooring down our new value
4154  */
4155  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4156  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4157  else
4158  consdata->lhs = newval;
4159  }
4160  if( !SCIPisInfinity(scip, consdata->rhs) )
4161  {
4162  newval = absscalar * consdata->rhs;
4163 
4164  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4165  * our new value
4166  */
4167  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4168  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4169  else
4170  consdata->rhs = newval;
4171  }
4172 
4173  consdataInvalidateActivities(consdata);
4174  consdata->cliquesadded = FALSE;
4175  consdata->implsadded = FALSE;
4176 
4177  return SCIP_OKAY;
4178 }
4179 
4180 /** perform deletion of variables in all constraints of the constraint handler */
4181 static
4183  SCIP* scip, /**< SCIP data structure */
4184  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4185  SCIP_CONS** conss, /**< array of constraints */
4186  int nconss /**< number of constraints */
4187  )
4188 {
4189  SCIP_CONSDATA* consdata;
4190  int i;
4191  int v;
4192 
4193  assert(scip != NULL);
4194  assert(conshdlr != NULL);
4195  assert(conss != NULL);
4196  assert(nconss >= 0);
4197  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4198 
4199  /* iterate over all constraints */
4200  for( i = 0; i < nconss; i++ )
4201  {
4202  consdata = SCIPconsGetData(conss[i]);
4203 
4204  /* constraint is marked, that some of its variables were deleted */
4205  if( consdata->varsdeleted )
4206  {
4207  /* iterate over all variables of the constraint and delete them from the constraint */
4208  for( v = consdata->nvars - 1; v >= 0; --v )
4209  {
4210  if( SCIPvarIsDeleted(consdata->vars[v]) )
4211  {
4212  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4213  }
4214  }
4215  consdata->varsdeleted = FALSE;
4216  }
4217  }
4218 
4219  return SCIP_OKAY;
4220 }
4221 
4222 
4223 /** normalizes a linear constraint with the following rules:
4224  * - if all coefficients have them same absolute value, change them to (-)1.0
4225  * - multiplication with +1 or -1:
4226  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4227  * if the current rule doesn't determine the sign):
4228  * 1. the right hand side must not be negative
4229  * 2. the right hand side must not be infinite
4230  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4231  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4232  * 5. multiply with +1
4233  * - rationals to integrals
4234  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4235  * by the smallest common multiple of all denominators to get integral coefficients.
4236  * Forbid large denominators due to numerical stability.
4237  * - division by greatest common divisor
4238  * If all coefficients are integral, divide them by the greatest common divisor.
4239  */
4240 static
4242  SCIP* scip, /**< SCIP data structure */
4243  SCIP_CONS* cons, /**< linear constraint to normalize */
4244  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4245  )
4246 {
4247  SCIP_CONSDATA* consdata;
4248  SCIP_Real* vals;
4249  SCIP_Longint scm;
4250  SCIP_Longint nominator;
4251  SCIP_Longint denominator;
4252  SCIP_Longint gcd;
4253  SCIP_Longint maxmult;
4254  SCIP_Real epsilon;
4255  SCIP_Real feastol;
4256  SCIP_Real maxabsval;
4257  SCIP_Real minabsval;
4258  SCIP_Bool success;
4259  SCIP_Bool onlyintegral;
4260  int nvars;
4261  int mult;
4262  int nposcoeffs;
4263  int nnegcoeffs;
4264  int i;
4265  int v;
4266 
4267  assert(scip != NULL);
4268  assert(cons != NULL);
4269  assert(infeasible != NULL);
4270 
4271  *infeasible = FALSE;
4272 
4273  /* we must not change a modifiable constraint in any way */
4274  if( SCIPconsIsModifiable(cons) )
4275  return SCIP_OKAY;
4276 
4277  /* get constraint data */
4278  consdata = SCIPconsGetData(cons);
4279  assert(consdata != NULL);
4280 
4281  /* check, if the constraint is already normalized */
4282  if( consdata->normalized )
4283  return SCIP_OKAY;
4284 
4285  /* get coefficient arrays */
4286  vals = consdata->vals;
4287  nvars = consdata->nvars;
4288  assert(nvars == 0 || vals != NULL);
4289 
4290  if( nvars == 0 )
4291  {
4292  consdata->normalized = TRUE;
4293  return SCIP_OKAY;
4294  }
4295 
4296  assert(vals != NULL);
4297 
4298  /* get maximal and minimal absolute coefficient */
4299  maxabsval = consdataGetMaxAbsval(consdata);
4300  minabsval = consdataGetMinAbsval(consdata);
4301 
4302  /* return if scaling by maxval will eliminate coefficients */
4303  if( SCIPisZero(scip, minabsval/maxabsval) )
4304  return SCIP_OKAY;
4305 
4306  /* check if all coefficients are in absolute value equal, and not 1.0 */
4307  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4308  {
4309  SCIP_Bool abscoefsequ;
4310 
4311  abscoefsequ = TRUE;
4312 
4313  for( v = nvars - 1; v >= 0; --v )
4314  {
4315  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4316  {
4317  abscoefsequ = FALSE;
4318  break;
4319  }
4320  }
4321 
4322  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4323  if( abscoefsequ )
4324  {
4325  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4326  SCIPdebugPrintCons(scip, cons, NULL);
4327  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4328 
4329  if( consdata->validmaxabsval )
4330  {
4331  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4332  consdata->maxabsval = 1.0;
4333  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4334  consdata->minabsval = 1.0;
4335 
4336  maxabsval = 1.0;
4337  }
4338  else
4339  {
4340  /* get maximal absolute coefficient */
4341  maxabsval = consdataGetMaxAbsval(consdata);
4342  }
4343 
4344  /* get new consdata information, because scaleCons() might have deleted variables */
4345  vals = consdata->vals;
4346  nvars = consdata->nvars;
4347 
4348  assert(nvars == 0 || vals != NULL);
4349  }
4350  }
4351 
4352  /* nvars might have changed */
4353  if( nvars == 0 )
4354  {
4355  consdata->normalized = TRUE;
4356  return SCIP_OKAY;
4357  }
4358 
4359  assert(vals != NULL);
4360 
4361  /* calculate the maximal multiplier for common divisor calculation:
4362  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4363  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4364  * additionally, we don't want to scale the constraint if this would lead to too
4365  * large coefficients
4366  */
4367  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4368  feastol = SCIPfeastol(scip);
4369  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4370 
4371  if( !consdata->hasnonbinvalid )
4372  consdataCheckNonbinvar(consdata);
4373 
4374  /* if all variables are of integral type we will allow a greater multiplier */
4375  if( !consdata->hascontvar )
4376  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4377  else
4378  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4379 
4380  /*
4381  * multiplication with +1 or -1
4382  */
4383  mult = 0;
4384 
4385  /* 1. the right hand side must not be negative */
4386  if( SCIPisPositive(scip, consdata->lhs) )
4387  mult = +1;
4388  else if( SCIPisNegative(scip, consdata->rhs) )
4389  mult = -1;
4390 
4391  if( mult == 0 )
4392  {
4393  /* 2. the right hand side must not be infinite */
4394  if( SCIPisInfinity(scip, -consdata->lhs) )
4395  mult = +1;
4396  else if( SCIPisInfinity(scip, consdata->rhs) )
4397  mult = -1;
4398  }
4399 
4400  if( mult == 0 )
4401  {
4402  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4403  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4404  mult = +1;
4405  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4406  mult = -1;
4407  }
4408 
4409  if( mult == 0 )
4410  {
4411  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4412  nposcoeffs = 0;
4413  nnegcoeffs = 0;
4414  for( i = 0; i < nvars; ++i )
4415  {
4416  if( vals[i] > 0.0 )
4417  nposcoeffs++;
4418  else
4419  nnegcoeffs++;
4420  }
4421  if( nposcoeffs > nnegcoeffs )
4422  mult = +1;
4423  else if( nposcoeffs < nnegcoeffs )
4424  mult = -1;
4425  }
4426 
4427  if( mult == 0 )
4428  {
4429  /* 5. multiply with +1 */
4430  mult = +1;
4431  }
4432 
4433  assert(mult == +1 || mult == -1);
4434  if( mult == -1 )
4435  {
4436  /* scale the constraint with -1 */
4437  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4438  SCIPdebugPrintCons(scip, cons, NULL);
4439  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4440 
4441  /* scalecons() can delete variables, but scaling with -1 should not do that */
4442  assert(nvars == consdata->nvars);
4443  }
4444 
4445  /*
4446  * rationals to integrals
4447  *
4448  * @todo try scaling only on behalf of non-continuous variables
4449  */
4450  success = TRUE;
4451  scm = 1;
4452  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4453  {
4454  if( !SCIPisIntegral(scip, vals[i]) )
4455  {
4456  /* epsilon has been slightly decreased above - to be on the safe side */
4457  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4458  if( success )
4459  scm = SCIPcalcSmaComMul(scm, denominator);
4460  }
4461  }
4462  assert(scm >= 1);
4463 
4464  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4465  * their greatest common divisor
4466  */
4467  onlyintegral = TRUE;
4468  if( scm == 1 )
4469  {
4470  for( i = nvars - 1; i >= 0; --i )
4471  {
4472  if( !SCIPisIntegral(scip, vals[i]) )
4473  {
4474  onlyintegral = FALSE;
4475  break;
4476  }
4477  }
4478  }
4479 
4480  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4481  if( success && scm != 1 )
4482  {
4483  /* scale the constraint with the smallest common multiple of all denominators */
4484  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4485  SCIPdebugPrintCons(scip, cons, NULL);
4486  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4487 
4488  if( consdata->validmaxabsval )
4489  {
4490  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4491  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4492  {
4493  consdata->validmaxabsval = FALSE;
4494  consdata->maxabsval = SCIP_INVALID;
4495  consdataCalcMaxAbsval(consdata);
4496  }
4497  }
4498 
4499  if( consdata->validminabsval )
4500  {
4501  consdata->minabsval *= REALABS((SCIP_Real)scm);
4502  if( !SCIPisIntegral(scip, consdata->minabsval) )
4503  {
4504  consdata->validminabsval = FALSE;
4505  consdata->minabsval = SCIP_INVALID;
4506  consdataCalcMinAbsval(consdata);
4507  }
4508  }
4509 
4510  /* get new consdata information, because scalecons() might have deleted variables */
4511  vals = consdata->vals;
4512  nvars = consdata->nvars;
4513  assert(nvars == 0 || vals != NULL);
4514  }
4515 
4516  /*
4517  * division by greatest common divisor
4518  */
4519  if( success && nvars >= 1 )
4520  {
4521  /* all coefficients are integral: divide them by their greatest common divisor */
4522  assert(SCIPisIntegral(scip, vals[0]));
4523 
4524  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4525  for( i = 1; i < nvars && gcd > 1; ++i )
4526  {
4527  assert(SCIPisIntegral(scip, vals[i]));
4528  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4529  }
4530 
4531  if( gcd > 1 )
4532  {
4533  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4534  if( !consdata->hascontvar && onlyintegral )
4535  {
4536  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4537  {
4538  *infeasible = TRUE;
4539 
4540  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4541  SCIPdebugPrintCons(scip, cons, NULL);
4542 
4543  return SCIP_OKAY;
4544  }
4545  }
4546 
4547  /* divide the constraint by the greatest common divisor of the coefficients */
4548  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4549  SCIPdebugPrintCons(scip, cons, NULL);
4550  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4551 
4552  if( consdata->validmaxabsval )
4553  {
4554  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4555  }
4556  if( consdata->validminabsval )
4557  {
4558  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4559  }
4560  }
4561  }
4562 
4563  /* mark constraint to be normalized */
4564  consdata->normalized = TRUE;
4565 
4566  SCIPdebugMsg(scip, "normalized constraint:\n");
4567  SCIPdebugPrintCons(scip, cons, NULL);
4568 
4569  return SCIP_OKAY;
4570 }
4571 
4572 /** replaces multiple occurrences of a variable by a single coefficient */
4573 static
4575  SCIP* scip, /**< SCIP data structure */
4576  SCIP_CONS* cons /**< linear constraint */
4577  )
4578 {
4579  SCIP_CONSDATA* consdata;
4580  SCIP_VAR* var;
4581  SCIP_Real valsum;
4582  int v;
4583 
4584  assert(scip != NULL);
4585  assert(cons != NULL);
4586 
4587  consdata = SCIPconsGetData(cons);
4588  assert(consdata != NULL);
4589 
4590  if( consdata->merged )
4591  return SCIP_OKAY;
4592 
4593  /* sort the constraint */
4594  SCIP_CALL( consdataSort(scip, consdata) );
4595 
4596  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4597  * backward direction is necessary, since delCoefPos() modifies the given position and
4598  * the subsequent ones
4599  */
4600  v = consdata->nvars-1;
4601  while( v >= 1 )
4602  {
4603  var = consdata->vars[v];
4604  if( consdata->vars[v-1] == var )
4605  {
4606  valsum = consdata->vals[v];
4607  do
4608  {
4609  SCIP_CALL( delCoefPos(scip, cons, v) );
4610  --v;
4611  valsum += consdata->vals[v];
4612  }
4613  while( v >= 1 && consdata->vars[v-1] == var );
4614 
4615  /* modify the last existing occurrence of the variable */
4616  assert(consdata->vars[v] == var);
4617  if( SCIPisZero(scip, valsum) )
4618  {
4619  SCIP_CALL( delCoefPos(scip, cons, v) );
4620 
4621  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4622  * delta needs to be recalculated on the next real propagation
4623  */
4624  if( consdata->maxactdeltavar == var )
4625  {
4626  consdata->maxactdelta = SCIP_INVALID;
4627  consdata->maxactdeltavar = NULL;
4628  }
4629  }
4630  else
4631  {
4632  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4633  }
4634  }
4635  --v;
4636  }
4637 
4638  consdata->merged = TRUE;
4639 
4640  return SCIP_OKAY;
4641 }
4642 
4643 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4644 static
4646  SCIP* scip, /**< SCIP data structure */
4647  SCIP_CONS* cons, /**< linear constraint */
4648  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4649  * information is not needed; in this case, we apply all fixings
4650  * instead of stopping after the first infeasible one */
4651  )
4652 {
4653  SCIP_CONSDATA* consdata;
4654  SCIP_VAR* var;
4655  SCIP_VAR** aggrvars;
4656  SCIP_Real val;
4657  SCIP_Real* aggrscalars;
4658  SCIP_Real fixedval;
4659  SCIP_Real aggrconst;
4660  int v;
4661  int naggrvars;
4662  int i;
4663 
4664  assert(scip != NULL);
4665  assert(cons != NULL);
4666 
4667  if( infeasible != NULL )
4668  *infeasible = FALSE;
4669 
4670  consdata = SCIPconsGetData(cons);
4671  assert(consdata != NULL);
4672 
4673  if( consdata->eventdata == NULL )
4674  {
4675  SCIP_CONSHDLR* conshdlr;
4676  SCIP_CONSHDLRDATA* conshdlrdata;
4677 
4678  conshdlr = SCIPconsGetHdlr(cons);
4679  assert(conshdlr != NULL);
4680 
4681  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4682  assert(conshdlrdata != NULL);
4683 
4684  /* catch bound change events of variables */
4685  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4686  assert(consdata->eventdata != NULL);
4687  }
4688 
4689  if( !consdata->removedfixings )
4690  {
4691  SCIP_Real lhssubtrahend;
4692  SCIP_Real rhssubtrahend;
4693 
4694  /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4695  * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4696  */
4697  assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4698 
4699  lhssubtrahend = 0.0;
4700  rhssubtrahend = 0.0;
4701 
4702  SCIPdebugMsg(scip, "applying fixings:\n");
4703  SCIPdebugPrintCons(scip, cons, NULL);
4704 
4705  v = 0;
4706  while( v < consdata->nvars )
4707  {
4708  var = consdata->vars[v];
4709  val = consdata->vals[v];
4710  assert(SCIPvarIsTransformed(var));
4711 
4712  switch( SCIPvarGetStatus(var) )
4713  {
4715  SCIPerrorMessage("original variable in transformed linear constraint\n");
4716  return SCIP_INVALIDDATA;
4717 
4718  case SCIP_VARSTATUS_LOOSE:
4719  case SCIP_VARSTATUS_COLUMN:
4720  ++v;
4721  break;
4722 
4723  case SCIP_VARSTATUS_FIXED:
4724  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4725  fixedval = SCIPvarGetLbGlobal(var);
4726  if( !SCIPisInfinity(scip, -consdata->lhs) )
4727  {
4728  if( SCIPisInfinity(scip, ABS(fixedval)) )
4729  {
4730  if( val * fixedval > 0.0 )
4731  {
4732  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4733  }
4734  else
4735  {
4736  if( infeasible != NULL )
4737  {
4738  /* if lhs gets infinity it means that the problem is infeasible */
4739  *infeasible = TRUE;
4740  return SCIP_OKAY;
4741  }
4742  else
4743  {
4744  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4745  }
4746  }
4747  }
4748  else
4749  lhssubtrahend += val * fixedval;
4750  }
4751  if( !SCIPisInfinity(scip, consdata->rhs) )
4752  {
4753  if( SCIPisInfinity(scip, ABS(fixedval)) )
4754  {
4755  if( val * fixedval > 0.0 )
4756  {
4757  if( infeasible != NULL )
4758  {
4759  /* if rhs gets -infinity it means that the problem is infeasible */
4760  *infeasible = TRUE;
4761  return SCIP_OKAY;
4762  }
4763  else
4764  {
4765  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4766  }
4767  }
4768  else
4769  {
4770  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4771  }
4772  }
4773  else
4774  rhssubtrahend += val * fixedval;
4775  }
4776  SCIP_CALL( delCoefPos(scip, cons, v) );
4777  break;
4778 
4780  {
4781  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4782  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4783  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4784 
4785  assert(activevar != NULL);
4786  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4787  assert(activevar != NULL);
4788 
4789  if( !SCIPisZero(scip, activescalar) )
4790  {
4791  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4792  }
4793 
4794  if( !SCIPisZero(scip, activeconstant) )
4795  {
4796  if( !SCIPisInfinity(scip, -consdata->lhs) )
4797  lhssubtrahend += activeconstant;
4798  if( !SCIPisInfinity(scip, consdata->rhs) )
4799  rhssubtrahend += activeconstant;
4800  }
4801 
4802  SCIP_CALL( delCoefPos(scip, cons, v) );
4803  break;
4804  }
4807  naggrvars = SCIPvarGetMultaggrNVars(var);
4808  aggrvars = SCIPvarGetMultaggrVars(var);
4809  aggrscalars = SCIPvarGetMultaggrScalars(var);
4810  for( i = 0; i < naggrvars; ++i )
4811  {
4812  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4813  }
4814  aggrconst = SCIPvarGetMultaggrConstant(var);
4815 
4816  if( !SCIPisInfinity(scip, -consdata->lhs) )
4817  lhssubtrahend += val * aggrconst;
4818  if( !SCIPisInfinity(scip, consdata->rhs) )
4819  rhssubtrahend += val * aggrconst;
4820 
4821  SCIP_CALL( delCoefPos(scip, cons, v) );
4822  break;
4823 
4825  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4826  aggrconst = SCIPvarGetNegationConstant(var);
4827 
4828  if( !SCIPisInfinity(scip, -consdata->lhs) )
4829  lhssubtrahend += val * aggrconst;
4830  if( !SCIPisInfinity(scip, consdata->rhs) )
4831  rhssubtrahend += val * aggrconst;
4832 
4833  SCIP_CALL( delCoefPos(scip, cons, v) );
4834  break;
4835 
4836  default:
4837  SCIPerrorMessage("unknown variable status\n");
4838  SCIPABORT();
4839  return SCIP_INVALIDDATA; /*lint !e527*/
4840  }
4841  }
4842 
4843  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4844  {
4845  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4846  * causing wrong fixings of other variables --> better use a real zero here;
4847  * for small numbers, polishing the difference might lead to wrong results -->
4848  * better use the exact difference in this case
4849  */
4850  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4851  {
4852  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4853  }
4854  else
4855  {
4856  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4857  }
4858  }
4859  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4860  {
4861  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4862  * causing wrong fixings of other variables --> better use a real zero here;
4863  * for small numbers, polishing the difference might lead to wrong results -->
4864  * better use the exact difference in this case
4865  */
4866  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4867  {
4868  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4869  }
4870  else
4871  {
4872  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4873  }
4874  }
4875  consdata->removedfixings = TRUE;
4876 
4877  SCIPdebugMsg(scip, "after fixings:\n");
4878  SCIPdebugPrintCons(scip, cons, NULL);
4879 
4880  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4881  * to clean up the constraint
4882  */
4883  SCIP_CALL( mergeMultiples(scip, cons) );
4884 
4885  SCIPdebugMsg(scip, "after merging:\n");
4886  SCIPdebugPrintCons(scip, cons, NULL);
4887  }
4888  assert(consdata->removedfixings);
4889 
4890 #ifndef NDEBUG
4891  /* check, if all fixings are applied */
4892  for( v = 0; v < consdata->nvars; ++v )
4893  assert(SCIPvarIsActive(consdata->vars[v]));
4894 #endif
4895 
4896  return SCIP_OKAY;
4897 }
4898 
4899 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4900  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4901  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4902  * conflict detecting constraint by using NULL as inferred variable
4903  */
4904 static
4906  SCIP* scip, /**< SCIP data structure */
4907  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4908  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4909  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4910  int inferpos, /**< position of the inferred variable in the vars array */
4911  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4912  )
4913 {
4914  SCIP_CONSDATA* consdata;
4915  SCIP_VAR** vars;
4916  SCIP_Real* vals;
4917  int nvars;
4918  int i;
4919 
4920  assert(scip != NULL);
4921  assert(cons != NULL);
4922 
4923  consdata = SCIPconsGetData(cons);
4925  assert(consdata != NULL);
4926 
4927  vars = consdata->vars;
4928  vals = consdata->vals;
4929  nvars = consdata->nvars;
4930 
4931  assert(vars != NULL || nvars == 0);
4932  assert(vals != NULL || nvars == 0);
4933 
4934  assert(-1 <= inferpos && inferpos < nvars);
4935  assert((infervar == NULL) == (inferpos == -1));
4936  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4937 
4938  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4939  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4940  * - if the right hand side is the reason, the minimal residual activity is responsible
4941  * - if the left hand side is the reason, the maximal residual activity is responsible
4942  */
4943 
4944  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4945  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4946  {
4947  SCIP_Real minresactivity;
4948  SCIP_Real maxresactivity;
4949  SCIP_Bool minisrelax;
4950  SCIP_Bool maxisrelax;
4951  SCIP_Bool isminsettoinfinity;
4952  SCIP_Bool ismaxsettoinfinity;
4953 
4954  minresactivity = -SCIPinfinity(scip);
4955  maxresactivity = SCIPinfinity(scip);
4956 
4957  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4958  if( infervar != NULL )
4959  {
4960  assert(vals != NULL); /* for flexelint */
4961  if( reasonisrhs )
4962  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4963  &minisrelax, NULL, &isminsettoinfinity, NULL);
4964  else
4965  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4966  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4967  }
4968  else
4969  {
4970  if( reasonisrhs )
4971  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4972  &minisrelax, NULL, &isminsettoinfinity, NULL);
4973  else
4974  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4975  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4976  }
4977 
4978  /* we can only do something clever, if the residual activity is finite and not relaxed */
4979  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4980  {
4981  SCIP_Real rescap;
4982  SCIP_Bool resactisinf;
4983 
4984  resactisinf = FALSE;
4985 
4986  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4987  * than its inferred bound
4988  */
4989  if( infervar != NULL )
4990  {
4991  assert(vals != NULL); /* for flexelint */
4992 
4993  if( reasonisrhs )
4994  {
4995  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4996  {
4997  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4998  if( SCIPisInfinity(scip, -minresactivity) )
4999  resactisinf = TRUE;
5000  }
5001  rescap = consdata->rhs - minresactivity;
5002  }
5003  else
5004  {
5005  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
5006  {
5007  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
5008  if( SCIPisInfinity(scip, maxresactivity) )
5009  resactisinf = TRUE;
5010  }
5011  rescap = consdata->lhs - maxresactivity;
5012  }
5013 
5014  if( reasonisrhs == (vals[inferpos] > 0.0) )
5015  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5016  else
5017  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5018  }
5019  else
5020  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5021 
5022  if( !resactisinf )
5023  {
5024  /* now add bounds as reasons until the residual capacity is exceeded */
5025  for( i = 0; i < nvars; ++i )
5026  {
5027  assert( vars != NULL && vals != NULL ); /* for lint */
5028 
5029  /* zero coefficients and the infered variable can be ignored */
5030  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5031  continue;
5032 
5033  /* check if the residual capacity is exceeded */
5034  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5035  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5036  break;
5037 
5038  /* update the residual capacity due to the local bound of this variable */
5039  if( reasonisrhs == (vals[i] > 0.0) )
5040  {
5041  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5042  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5043  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5044  }
5045  else
5046  {
5047  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5048  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5049  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5050  }
5051  }
5052  return SCIP_OKAY;
5053  }
5054  }
5055  }
5056 
5057  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5058  for( i = 0; i < nvars; ++i )
5059  {
5060  assert(vars != NULL); /* for flexelint */
5061  assert(vals != NULL); /* for flexelint */
5062 
5063  /* zero coefficients and the infered variable can be ignored */
5064  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5065  continue;
5066 
5067  if( reasonisrhs == (vals[i] > 0.0) )
5068  {
5069  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5070  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5071  }
5072  else
5073  {
5074  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5075  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5076  }
5077  }
5078 
5079  return SCIP_OKAY;
5080 }
5081 
5082 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5083  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5084  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5085  */
5086 static
5088  SCIP* scip, /**< SCIP data structure */
5089  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5090  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5091  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5092  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5093  )
5094 {
5095  SCIP_CONSDATA* consdata;
5096  SCIP_VAR** vars;
5097  int nvars;
5098  int v;
5099 
5100  assert(scip != NULL);
5101  assert(cons != NULL);
5102 
5103  consdata = SCIPconsGetData(cons);
5104  assert(consdata != NULL);
5105  vars = consdata->vars;
5106  nvars = consdata->nvars;
5107  assert(vars != NULL || nvars == 0);
5108  assert(-1 <= inferpos && inferpos < nvars);
5109  assert((infervar == NULL) == (inferpos == -1));
5110  assert(inferpos == -1 || vars != NULL);
5111  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5112 
5113  /* collect all fixed variables */
5114  for( v = nvars - 1; v >= 0; --v )
5115  {
5116  assert(vars != NULL); /* for flexelint */
5117 
5118  /* need to add old bounds before propagation of inferrence variable */
5119  if( vars[v] == infervar )
5120  {
5121  assert(vars[v] != NULL);
5122 
5123  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5124  {
5125  /* @todo get boundchange index before this last boundchange and correct the index */
5126  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5127  }
5128 
5129  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5130  {
5131  /* @todo get boundchange index before this last boundchange and correct the index */
5132  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5133  }
5134 
5135  continue;
5136  }
5137 
5138  /* check for fixed variables */
5139  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5140  {
5141  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5142  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5143  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5144  }
5145  }
5146 
5147  return SCIP_OKAY;
5148 }
5149 
5150 /** add reasoning variables to conflict candidate queue which led to the conflict */
5151 static
5153  SCIP* scip, /**< SCIP data structure */
5154  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5155  int nvars, /**< number of variables reasoning the infeasibility */
5156  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5157  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5158  )
5159 {
5160  int v;
5161 
5162  assert(scip != NULL);
5163 
5164  /* collect all variables for which the local bounds differ from their global bounds */
5165  for( v = nvars - 1; v >= 0; --v )
5166  {
5167  assert(vars != NULL);
5168 
5169  /* check for local bound changes variables */
5170  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5171  {
5172  /* add conflict bound */
5173  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5174  }
5175 
5176  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5177  {
5178  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5179  }
5180  }
5181 
5182  if( var != NULL )
5183  {
5184  if( bound < SCIPvarGetLbLocal(var) )
5185  {
5186  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5187  }
5188 
5189  if( bound > SCIPvarGetUbLocal(var) )
5190  {
5191  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5192  }
5193  }
5194 
5195  return SCIP_OKAY;
5196 }
5197 
5198 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5199  * propagation rule (see propagateCons()):
5200  * (1) activity residuals of all other variables tighten bounds of single variable
5201  */
5202 static
5204  SCIP* scip, /**< SCIP data structure */
5205  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5206  SCIP_VAR* infervar, /**< variable that was deduced */
5207  INFERINFO inferinfo, /**< inference information */
5208  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5209  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5210  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5211  )
5212 {
5213  SCIP_CONSDATA* consdata;
5214  SCIP_VAR** vars;
5215 #ifndef NDEBUG
5216  SCIP_Real* vals;
5217 #endif
5218  int nvars;
5219  int inferpos;
5220 
5221  assert(scip != NULL);
5222  assert(cons != NULL);
5223  assert(result != NULL);
5224 
5225  consdata = SCIPconsGetData(cons);
5226  assert(consdata != NULL);
5227  vars = consdata->vars;
5228  nvars = consdata->nvars;
5229 #ifndef NDEBUG
5230  vals = consdata->vals;
5231  assert(vars != NULL);
5232  assert(vals != NULL);
5233 #endif
5234 
5235  /* get the position of the inferred variable in the vars array */
5236  inferpos = inferInfoGetPos(inferinfo);
5237  if( inferpos >= nvars || vars[inferpos] != infervar )
5238  {
5239  /* find inference variable in constraint */
5240  /**@todo use a binary search here; the variables can be sorted by variable index */
5241  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5242  {}
5243  }
5244  assert(inferpos < nvars);
5245  assert(vars[inferpos] == infervar);
5246  assert(!SCIPisZero(scip, vals[inferpos]));
5247 
5248  switch( inferInfoGetProprule(inferinfo) )
5249  {
5250  case PROPRULE_1_RHS:
5251  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5252  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5253  * domain in order to not exceed the right hand side of the inequality
5254  */
5255  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5256  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5257  *result = SCIP_SUCCESS;
5258  break;
5259 
5260  case PROPRULE_1_LHS:
5261  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5262  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5263  * domain in order to not fall below the left hand side of the inequality
5264  */
5265  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5266  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5267  *result = SCIP_SUCCESS;
5268  break;
5269 
5270  case PROPRULE_1_RANGEDROW:
5271  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5272  * the given inference variable to their bounds in this given ranged row
5273  */
5274 
5275  /* check that we really have a ranged row here */
5276  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5277  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5278  *result = SCIP_SUCCESS;
5279  break;
5280 
5281  case PROPRULE_INVALID:
5282  default:
5283  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5284  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5285  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5286  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5287  SCIPinfoMessage(scip, NULL, ";\n");
5288  return SCIP_INVALIDDATA;
5289  }
5290 
5291  return SCIP_OKAY;
5292 }
5293 
5294 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5295 static
5297  SCIP* scip, /**< SCIP data structure */
5298  SCIP_CONS* cons, /**< conflict detecting constraint */
5299  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5300  )
5301 {
5302  /* conflict analysis can only be applied in solving stage and if it is turned on */
5304  return SCIP_OKAY;
5305 
5306  /* initialize conflict analysis */
5308 
5309  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5310  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5311 
5312  /* analyze the conflict */
5313  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5314 
5315  return SCIP_OKAY;
5316 }
5317 
5318 /** check if there is any hope of tightening some bounds */
5319 static
5321  SCIP_CONS* cons /**< linear constraint */
5322  )
5323 {
5324  SCIP_CONSDATA* consdata;
5325  int infcountmin;
5326  int infcountmax;
5327 
5328  consdata = SCIPconsGetData(cons);
5329  assert(consdata != NULL);
5330 
5331  infcountmin = consdata->minactivityneginf
5332  + consdata->minactivityposinf
5333  + consdata->minactivityneghuge
5334  + consdata->minactivityposhuge;
5335  infcountmax = consdata->maxactivityneginf
5336  + consdata->maxactivityposinf
5337  + consdata->maxactivityneghuge
5338  + consdata->maxactivityposhuge;
5340  if( infcountmin > 1 && infcountmax > 1 )
5341  return FALSE;
5342 
5343  return TRUE;
5344 }
5345 
5346 /** tighten upper bound */
5347 static
5349  SCIP* scip, /**< SCIP data structure */
5350  SCIP_CONS* cons, /**< linear constraint */
5351  int pos, /**< variable position */
5352  PROPRULE proprule, /**< propagation rule that deduced the value */
5353  SCIP_Real newub, /**< new upper bound */
5354  SCIP_Real oldub, /**< old upper bound */
5355  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5356  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5357  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5358  )
5359 {
5360  SCIP_CONSDATA* consdata;
5361  SCIP_VAR* var;
5362  SCIP_Real lb;
5363  SCIP_Bool infeasible;
5364  SCIP_Bool tightened;
5365 
5366  assert(cons != NULL);
5367  assert(!SCIPisInfinity(scip, newub));
5368 
5369  consdata = SCIPconsGetData(cons);
5370  assert(consdata != NULL);
5371  var = consdata->vars[pos];
5372  assert(var != NULL);
5373 
5374  lb = SCIPvarGetLbLocal(var);
5375  newub = SCIPadjustedVarUb(scip, var, newub);
5376 
5377  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5378  {
5379  SCIP_VARTYPE vartype;
5380 
5381  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5382  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5383 
5384  vartype = SCIPvarGetType(var);
5385 
5386  /* tighten upper bound */
5387  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5388 
5389  if( infeasible )
5390  {
5391  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5392  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5393 
5394  /* analyze conflict */
5395  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5396 
5397  *cutoff = TRUE;
5398  }
5399  else if( tightened )
5400  {
5401  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5402  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5403  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5404 
5405  (*nchgbds)++;
5406 
5407  /* if variable type was changed we might be able to upgrade the constraint */
5408  if( vartype != SCIPvarGetType(var) )
5409  consdata->upgradetried = FALSE;
5410  }
5411  }
5412  return SCIP_OKAY;
5413 }
5414 
5415 /** tighten lower bound */
5416 static
5418  SCIP* scip, /**< SCIP data structure */
5419  SCIP_CONS* cons, /**< linear constraint */
5420  int pos, /**< variable position */
5421  PROPRULE proprule, /**< propagation rule that deduced the value */
5422  SCIP_Real newlb, /**< new lower bound */
5423  SCIP_Real oldlb, /**< old lower bound */
5424  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5425  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5426  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5427  )
5428 {
5429  SCIP_CONSDATA* consdata;
5430  SCIP_VAR* var;
5431  SCIP_Real ub;
5432  SCIP_Bool infeasible;
5433  SCIP_Bool tightened;
5434 
5435  assert(cons != NULL);
5436  assert(!SCIPisInfinity(scip, newlb));
5437 
5438  consdata = SCIPconsGetData(cons);
5439  assert(consdata != NULL);
5440  var = consdata->vars[pos];
5441  assert(var != NULL);
5442 
5443  ub = SCIPvarGetUbLocal(var);
5444  newlb = SCIPadjustedVarLb(scip, var, newlb);
5445 
5446  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5447  {
5448  SCIP_VARTYPE vartype;
5449 
5450  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5451  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5452 
5453  vartype = SCIPvarGetType(var);
5454 
5455  /* tighten lower bound */
5456  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5457 
5458  if( infeasible )
5459  {
5460  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5461  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5462 
5463  /* analyze conflict */
5464  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5465 
5466  *cutoff = TRUE;
5467  }
5468  else if( tightened )
5469  {
5470  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5471  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5472  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5473 
5474  (*nchgbds)++;
5475 
5476  /* if variable type was changed we might be able to upgrade the constraint */
5477  if( vartype != SCIPvarGetType(var) )
5478  consdata->upgradetried = FALSE;
5479  }
5480  }
5481  return SCIP_OKAY;
5482 }
5483 
5484 /** tightens bounds of a single variable due to activity bounds (easy case) */
5485 static
5487  SCIP* scip, /**< SCIP data structure */
5488  SCIP_CONS* cons, /**< linear constraint */
5489  int pos, /**< position of the variable in the vars array */
5490  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5491  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5492  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5493  )
5494 {
5495  SCIP_CONSDATA* consdata;
5496  SCIP_VAR* var;
5497  SCIP_Real val;
5498  SCIP_Real lb;
5499  SCIP_Real ub;
5500  SCIP_Real lhs;
5501  SCIP_Real rhs;
5502 
5503  assert(scip != NULL);
5504  assert(cons != NULL);
5505  assert(cutoff != NULL);
5506  assert(nchgbds != NULL);
5507 
5508  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5509  if( SCIPconsIsModifiable(cons) )
5510  return SCIP_OKAY;
5511 
5512  consdata = SCIPconsGetData(cons);
5513  assert(consdata != NULL);
5514  assert(0 <= pos && pos < consdata->nvars);
5515 
5516  *cutoff = FALSE;
5517 
5518  var = consdata->vars[pos];
5519  assert(var != NULL);
5520 
5521  /* we cannot tighten bounds of multi-aggregated variables */
5523  return SCIP_OKAY;
5524 
5525  val = consdata->vals[pos];
5526  lhs = consdata->lhs;
5527  rhs = consdata->rhs;
5528  assert(!SCIPisZero(scip, val));
5529  assert(!SCIPisInfinity(scip, lhs));
5530  assert(!SCIPisInfinity(scip, -rhs));
5531 
5532  lb = SCIPvarGetLbLocal(var);
5533  ub = SCIPvarGetUbLocal(var);
5534  assert(SCIPisLE(scip, lb, ub));
5535 
5536  /* recompute activities if needed */
5537  if( !consdata->validactivities )
5538  consdataCalcActivities(scip, consdata);
5539  assert(consdata->validactivities);
5540  if( !consdata->validminact )
5541  consdataRecomputeMinactivity(scip, consdata);
5542  assert(consdata->validminact);
5543 
5544  if( val > 0.0 )
5545  {
5546  /* check, if we can tighten the variable's upper bound */
5547  if( !SCIPisInfinity(scip, rhs) )
5548  {
5549  SCIP_Real slack;
5550  SCIP_Real alpha;
5551 
5552  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5553  assert(consdata->validminact);
5554 
5555  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5556  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5557  {
5558  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5559  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5560 
5561  *cutoff = TRUE;
5562  return SCIP_OKAY;
5563  }
5564 
5565  slack = rhs - consdata->minactivity;
5566 
5567  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5568  * it to zero
5569  */
5570  if( !SCIPisPositive(scip, slack) )
5571  slack = 0.0;
5572 
5573  alpha = val * (ub - lb);
5574  assert(!SCIPisNegative(scip, alpha));
5575 
5576  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5577  {
5578  SCIP_Real newub;
5579 
5580  /* compute new upper bound */
5581  newub = lb + (slack / val);
5582 
5583  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5584 
5585  if( *cutoff )
5586  {
5587  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5588  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5589 
5590  return SCIP_OKAY;
5591  }
5592 
5593  /* collect the new upper bound which is needed for the lower bound computation */
5594  ub = SCIPvarGetUbLocal(var);
5595  }
5596  }
5597 
5598  /* check, if we can tighten the variable's lower bound */
5599  if( !SCIPisInfinity(scip, -lhs) )
5600  {
5601  SCIP_Real slack;
5602  SCIP_Real alpha;
5603 
5604  /* make sure the max activity is reliable */
5605  if( !consdata->validmaxact )
5606  {
5607  consdataRecomputeMaxactivity(scip, consdata);
5608  }
5609  assert(consdata->validmaxact);
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  *cutoff = TRUE;
5617  return SCIP_OKAY;
5618  }
5619 
5620  slack = consdata->maxactivity - lhs;
5621 
5622  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5623  * it to zero
5624  */
5625  if( !SCIPisPositive(scip, slack) )
5626  slack = 0.0;
5627 
5628  alpha = val * (ub - lb);
5629  assert(!SCIPisNegative(scip, alpha));
5630 
5631  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5632  {
5633  SCIP_Real newlb;
5634 
5635  /* compute new lower bound */
5636  newlb = ub - (slack / val);
5637 
5638  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5639 
5640  if( *cutoff )
5641  {
5642  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5643  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5644 
5645  return SCIP_OKAY;
5646  }
5647  }
5648  }
5649  }
5650  else
5651  {
5652  /* check, if we can tighten the variable's lower bound */
5653  if( !SCIPisInfinity(scip, rhs) )
5654  {
5655  SCIP_Real slack;
5656  SCIP_Real alpha;
5657 
5658  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5659  assert(consdata->validminact);
5660 
5661  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5662  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5663  {
5664  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5665  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5666 
5667  *cutoff = TRUE;
5668  return SCIP_OKAY;
5669  }
5670 
5671  slack = rhs - consdata->minactivity;
5672 
5673  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5674  * it to zero
5675  */
5676  if( !SCIPisPositive(scip, slack) )
5677  slack = 0.0;
5678 
5679  alpha = val * (lb - ub);
5680  assert(!SCIPisNegative(scip, alpha));
5681 
5682  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5683  {
5684  SCIP_Real newlb;
5685 
5686  /* compute new lower bound */
5687  newlb = ub + slack / val;
5688 
5689  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5690 
5691  if( *cutoff )
5692  {
5693  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5694  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5695 
5696  return SCIP_OKAY;
5697  }
5698  /* collect the new lower bound which is needed for the upper bound computation */
5699  lb = SCIPvarGetLbLocal(var);
5700  }
5701  }
5702 
5703  /* check, if we can tighten the variable's upper bound */
5704  if( !SCIPisInfinity(scip, -lhs) )
5705  {
5706  SCIP_Real slack;
5707  SCIP_Real alpha;
5708 
5709  /* make sure the max activity is reliable */
5710  if( !consdata->validmaxact )
5711  {
5712  consdataRecomputeMaxactivity(scip, consdata);
5713  }
5714  assert(consdata->validmaxact);
5715 
5716  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5717  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5718  {
5719  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5720  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5721 
5722  *cutoff = TRUE;
5723  return SCIP_OKAY;
5724  }
5725 
5726  slack = consdata->maxactivity - lhs;
5727 
5728  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5729  * it to zero
5730  */
5731  if( !SCIPisPositive(scip, slack) )
5732  slack = 0.0;
5733 
5734  alpha = val * (lb - ub);
5735  assert(!SCIPisNegative(scip, alpha));
5736 
5737  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5738  {
5739  SCIP_Real newub;
5740 
5741  /* compute new upper bound */
5742  newub = lb - (slack / val);
5743 
5744  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5745 
5746  if( *cutoff )
5747  {
5748  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5749  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5750 
5751  return SCIP_OKAY;
5752  }
5753  }
5754  }
5755  }
5756 
5757  return SCIP_OKAY;
5758 }
5759 
5760 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5761 static
5763  SCIP* scip, /**< SCIP data structure */
5764  SCIP_CONS* cons, /**< conflict detecting constraint */
5765  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5766  int nvars, /**< number of variables reasoning the infeasibility */
5767  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5768  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5769  )
5770 {
5771 #ifndef NDEBUG
5772  SCIP_CONSDATA* consdata;
5773 
5774  assert(scip != NULL);
5775  assert(cons != NULL);
5776 
5777  consdata = SCIPconsGetData(cons);
5778  assert(consdata != NULL);
5779  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5780 #endif
5782  /* conflict analysis can only be applied in solving stage and if it is turned on */
5784  return SCIP_OKAY;
5785 
5786  /* initialize conflict analysis */
5788 
5789  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5790  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5791 
5792  /* add reasoning variables to conflict candidate queue which led to the conflict */
5793  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5794 
5795  /* analyze the conflict */
5796  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5797 
5798  return SCIP_OKAY;
5799 }
5800 
5801 /** propagate ranged rows
5802  *
5803  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5804  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5805  * variables better.
5806  *
5807  * Example:
5808  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5809  *
5810  * x3 needs to be a multiple of 3, so the instance is infeasible.
5811  *
5812  * Example:
5813  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5814  *
5815  * The only possible value for x3 is 2, so the variable will be fixed.
5816  *
5817  * @todo add holes if possible
5818  */
5819 static
5821  SCIP* scip, /**< SCIP data structure */
5822  SCIP_CONS* cons, /**< linear constraint */
5823  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5824  int* nfixedvars, /**< pointer to count number of fixed variables */
5825  int* nchgbds, /**< pointer to count the number of bound changes */
5826  int* naddconss /**< pointer to count number of added constraints */
5827  )
5828 {
5829  SCIP_CONSHDLRDATA* conshdlrdata;
5830  SCIP_CONSHDLR* conshdlr;
5831  SCIP_CONSDATA* consdata;
5832  SCIP_VAR** infcheckvars;
5833  SCIP_Real* infcheckvals;
5834  SCIP_Real minactinfvars;
5835  SCIP_Real maxactinfvars;
5836  SCIP_Real lb;
5837  SCIP_Real ub;
5838  SCIP_Real feastol;
5839  SCIP_Real fixedact;
5840  SCIP_Real lhs;
5841  SCIP_Real rhs;
5842  SCIP_Real absminbincoef;
5843  SCIP_Longint gcd;
5844  SCIP_Longint gcdtmp;
5845  SCIP_Bool minactinfvarsinvalid;
5846  SCIP_Bool maxactinfvarsinvalid;
5847  SCIP_Bool possiblegcd;
5848  SCIP_Bool gcdisone;
5849  SCIP_Bool addartconss;
5850  int ninfcheckvars;
5851  int nunfixedvars;
5852  int nfixedconsvars;
5853  int ncontvars;
5854  int pos;
5855  int v;
5856 
5857  assert(scip != NULL);
5858  assert(cons != NULL);
5859  assert(cutoff != NULL);
5860  assert(nfixedvars != NULL);
5861  assert(nchgbds != NULL);
5862  assert(naddconss != NULL);
5863 
5864  /* modifiable constraint can be changed so we do not have all necessary information */
5865  if( SCIPconsIsModifiable(cons) )
5866  return SCIP_OKAY;
5867 
5868  consdata = SCIPconsGetData(cons);
5869  assert(consdata != NULL);
5870 
5871  /* we already did full ranged row propagation */
5872  if( consdata->rangedrowpropagated == 2 )
5873  return SCIP_OKAY;
5874 
5875  /* at least three variables are needed */
5876  if( consdata->nvars < 3 )
5877  return SCIP_OKAY;
5878 
5879  /* do nothing on normal inequalities */
5880  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5881  return SCIP_OKAY;
5882 
5883  /* get constraint handler data */
5884  conshdlr = SCIPconsGetHdlr(cons);
5885  assert(conshdlr != NULL);
5886  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5887  assert(conshdlrdata != NULL);
5888 
5889  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5890 
5891  /* we may add artificial constraints */
5892  if( addartconss )
5893  consdata->rangedrowpropagated = 2;
5894  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5895  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5896  * artificial constraints
5897  */
5898  else
5899  {
5900  if( consdata->rangedrowpropagated > 0 )
5901  return SCIP_OKAY;
5902 
5903  consdata->rangedrowpropagated = 1;
5904  }
5905  fixedact = 0;
5906  nfixedconsvars = 0;
5907  /* calculate fixed activity and number of fixed variables */
5908  for( v = consdata->nvars - 1; v >= 0; --v )
5909  {
5910  /* all zero coefficients should be eliminated */
5911  assert(!SCIPisZero(scip, consdata->vals[v]));
5912 
5913  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5914  {
5915  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5916  ++nfixedconsvars;
5917  }
5918  }
5919 
5920  /* do not work with huge fixed activities */
5921  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5922  return SCIP_OKAY;
5923 
5924  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5925  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5926  lhs = consdata->lhs - fixedact;
5927  rhs = consdata->rhs - fixedact;
5928  nunfixedvars = consdata->nvars - nfixedconsvars;
5929 
5930  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5931  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5932  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5933 
5934  absminbincoef = SCIP_REAL_MAX;
5935  ncontvars = 0;
5936  gcdisone = TRUE;
5937  possiblegcd = TRUE;
5938 
5939  /* we now partition all unfixed variables in two groups:
5940  *
5941  * the first one contains all integral variable with integral
5942  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5943  * given
5944  *
5945  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5946  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5947  */
5948 
5949  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5950  * variables
5951  */
5952  ninfcheckvars = 0;
5953  v = -1;
5954  pos = -1;
5955  do
5956  {
5957  ++v;
5958 
5959  /* partition the variables, do not change the order of collection, because it might be used later on */
5960  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5961  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5962  {
5963  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5964  {
5965  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5966  {
5967  ++ncontvars;
5968  }
5969  else if( SCIPvarIsBinary(consdata->vars[v]) )
5970  {
5971  SCIP_Real absval;
5972 
5973  absval = REALABS(consdata->vals[v]);
5974 
5975  if( absminbincoef > absval )
5976  absminbincoef = absval;
5977  }
5978 
5979  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5980  possiblegcd = FALSE;
5981  infcheckvars[ninfcheckvars] = consdata->vars[v];
5982  infcheckvals[ninfcheckvars] = consdata->vals[v];
5983  ++ninfcheckvars;
5984 
5985  if( pos == -1 )
5986  pos = v;
5987  }
5988  ++v;
5989  }
5990  }
5991  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5992 
5993  /* if the first group of variables is empty, we stop */
5994  /* @todo try to propagate/split up a constraint of the form:
5995  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5996  * 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]
5997  */
5998  if( v == consdata->nvars )
5999  goto TERMINATE;
6000 
6001  /* we need at least two non-continuous variables */
6002  if( ncontvars + 2 > nunfixedvars )
6003  goto TERMINATE;
6004 
6005  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6006  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6007 
6008  feastol = SCIPfeastol(scip);
6009 
6010  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6011  assert(gcd >= 2);
6012 
6013  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6014  * calculate gcd over the first part of variables */
6015  for( ; v < consdata->nvars; ++v )
6016  {
6017  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6018  continue;
6019 
6020  if( SCIPvarIsBinary(consdata->vars[v]) )
6021  {
6022  SCIP_Real absval;
6023 
6024  absval = REALABS(consdata->vals[v]);
6025 
6026  if( absminbincoef > absval )
6027  absminbincoef = absval;
6028  }
6029 
6030  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6031  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6032  {
6033  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6034  ++ncontvars;
6035 
6036  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6037  possiblegcd = FALSE;
6038  infcheckvars[ninfcheckvars] = consdata->vars[v];
6039  infcheckvals[ninfcheckvars] = consdata->vals[v];
6040 
6041  ++ninfcheckvars;
6042 
6043  if( pos == -1 )
6044  pos = v;
6045  }
6046  else
6047  {
6048  assert(REALABS(consdata->vals[v]) > 1.5);
6049 
6050  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6051  assert(gcdtmp >= 1);
6052 
6053  if( gcdtmp == 1 )
6054  {
6055  infcheckvars[ninfcheckvars] = consdata->vars[v];
6056  infcheckvals[ninfcheckvars] = consdata->vals[v];
6057 
6058  ++ninfcheckvars;
6059 
6060  if( pos == -1 )
6061  pos = v;
6062  }
6063  else
6064  gcd = gcdtmp;
6065  }
6066  }
6067  assert(gcd >= 2);
6068 
6069  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6070  * normalizeCons() */
6071  if( ninfcheckvars == 0 )
6072  goto TERMINATE;
6073 
6074  assert(pos >= 0);
6075 
6076  minactinfvarsinvalid = FALSE;
6077  maxactinfvarsinvalid = FALSE;
6078  maxactinfvars = 0.0;
6079  minactinfvars = 0.0;
6080 
6081  /* calculate activities over all infcheckvars */
6082  for( v = ninfcheckvars - 1; v >= 0; --v )
6083  {
6084  lb = SCIPvarGetLbLocal(infcheckvars[v]);
6085  ub = SCIPvarGetUbLocal(infcheckvars[v]);
6086 
6087  if( SCIPisInfinity(scip, -lb) )
6088  {
6089  if( infcheckvals[v] < 0.0 )
6090  maxactinfvarsinvalid = TRUE;
6091  else
6092  minactinfvarsinvalid = TRUE;
6093  }
6094  else
6095  {
6096  if( infcheckvals[v] < 0.0 )
6097  maxactinfvars += infcheckvals[v] * lb;
6098  else
6099  minactinfvars += infcheckvals[v] * lb;
6100  }
6101 
6102  if( SCIPisInfinity(scip, ub) )
6103  {
6104  if( infcheckvals[v] > 0.0 )
6105  maxactinfvarsinvalid = TRUE;
6106  else
6107  minactinfvarsinvalid = TRUE;
6108  }
6109  else
6110  {
6111  if( infcheckvals[v] > 0.0 )
6112  maxactinfvars += infcheckvals[v] * ub;
6113  else
6114  minactinfvars += infcheckvals[v] * ub;
6115  }
6116 
6117  /* better abort on to big values */
6118  if( SCIPisHugeValue(scip, -minactinfvars) )
6119  minactinfvarsinvalid = TRUE;
6120  if( SCIPisHugeValue(scip, maxactinfvars) )
6121  maxactinfvarsinvalid = TRUE;
6122 
6123  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6124  goto TERMINATE;
6125  }
6126  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6127 
6128  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6129  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6130 
6131  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6132  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6133  * activities */
6134  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6135  * !!!note!!!
6136  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6137  * are not at their global bound
6138  */
6139 
6140  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6141  * infeasibility */
6142  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6143  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6144  {
6145  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6146  SCIPdebugPrintCons(scip, cons, NULL);
6147 
6148  /* start conflict analysis */
6149  /* @todo improve conflict analysis by adding relaxed bounds */
6150  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6151 
6152  *cutoff = TRUE;
6153  }
6154  else if( ncontvars == 0 )
6155  {
6156  SCIP_Longint gcdinfvars = -1;
6157 
6158  /* check for gcd over all infcheckvars */
6159  if( possiblegcd )
6160  {
6161  v = ninfcheckvars - 1;
6162  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6163  assert(gcdinfvars >= 2);
6164 
6165  for( ; v >= 0 && gcdinfvars >= 2; --v )
6166  {
6167  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6168  }
6169  }
6170  else if( gcdisone )
6171  gcdinfvars = 1;
6172 
6173  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6174 
6175  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6176  if( gcdinfvars >= 1 )
6177  {
6178  SCIP_Real value;
6179  SCIP_Real value2;
6180  SCIP_Real minvalue = SCIP_INVALID;
6181  SCIP_Real maxvalue = SCIP_INVALID;
6182  int nsols = 0;
6183 
6184  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6185 
6186  /* check how many possible solutions exist */
6187  while( SCIPisLE(scip, value, maxactinfvars) )
6188  {
6189  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6190 
6191  /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6192  if( !SCIPisGE(scip, value2, lhs) )
6193  {
6194  value2 += gcd;
6195  }
6196 
6197  if( SCIPisLE(scip, value2, rhs) )
6198  {
6199  ++nsols;
6200 
6201  /* early termination if we found more than two solutions */
6202  if( nsols == 3 )
6203  break;
6204 
6205  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6206  minvalue = value;
6207 
6208  maxvalue = value;
6209  }
6210  value += gcdinfvars;
6211  }
6212  assert(nsols < 2 || minvalue <= maxvalue);
6213 
6214  /* determine last possible solution for better bounding */
6215  if( nsols == 3 )
6216  {
6217 #ifndef NDEBUG
6218  SCIP_Real secondsolval = maxvalue;
6219 #endif
6220  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6221 
6222  /* check how many possible solutions exist */
6223  while( SCIPisGE(scip, value, minactinfvars) )
6224  {
6225  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6226 
6227  /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6228  if( !SCIPisLE(scip, value2, rhs) )
6229  {
6230  value2 -= gcd;
6231  }
6232 
6233  if( SCIPisGE(scip, value2, lhs) )
6234  {
6235  maxvalue = value;
6236  assert(maxvalue > minvalue);
6237  break;
6238  }
6239  value -= gcdinfvars;
6240  }
6241  assert(maxvalue > secondsolval);
6242  }
6243 
6244  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6245  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6246 
6247  /* no possible solution found */
6248  if( nsols == 0 )
6249  {
6250  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6251  gcdinfvars, gcd, lhs, rhs);
6252  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6253  SCIPdebugPrintCons(scip, cons, NULL);
6254 
6255  /* start conflict analysis */
6256  /* @todo improve conflict analysis by adding relaxed bounds */
6257  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6258 
6259  *cutoff = TRUE;
6260  }
6261  /* if only one solution exist we can extract a new constraint or fix variables */
6262  else if( nsols == 1 )
6263  {
6264  assert(minvalue == maxvalue); /*lint !e777*/
6265 
6266  /* we can fix the only variable in our second set of variables */
6267  if( ninfcheckvars == 1 )
6268  {
6269  SCIP_Bool fixed;
6270 
6271  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6272 
6273  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6274  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6275  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6276 
6277  /* fix variable to only possible value */
6278  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6279  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6280 
6281  if( *cutoff )
6282  {
6283  /* start conflict analysis */
6284  /* @todo improve conflict analysis by adding relaxed bounds */
6285  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6286  }
6287 
6288  if( fixed )
6289  ++(*nfixedvars);
6290  }
6291  else
6292  {
6293  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6294  if( ninfcheckvars == nunfixedvars - 1 )
6295  {
6296  SCIP_Real bound;
6297  SCIP_Bool foundvar = FALSE;
6298  SCIP_Bool fixed;
6299  int w = 0;
6300 
6301  assert(ninfcheckvars > 0);
6302 
6303  /* find variable which is not an infcheckvar and fix it */
6304  for( v = 0; v < consdata->nvars - 1; ++v )
6305  {
6306  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6307  {
6308  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6309  {
6310 #ifndef NDEBUG
6311  int v2 = v + 1;
6312  int w2 = w;
6313 
6314  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6315 
6316  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6317  {
6318  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6319  continue;
6320 
6321  assert(consdata->vars[v2] == infcheckvars[w2]);
6322  ++w2;
6323  }
6324  assert(w2 == ninfcheckvars);
6325 #endif
6326  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6327 
6328  foundvar = TRUE;
6329 
6330  if( consdata->vals[v] < 0 )
6331  {
6332  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6333  }
6334  else
6335  {
6336  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6337  }
6338 
6339  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6340  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6341  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6342 
6343  /* fix variable to only possible value */
6344  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6345  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6346 
6347  if( *cutoff )
6348  {
6349  /* start conflict analysis */
6350  /* @todo improve conflict analysis by adding relaxed bounds */
6351  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6352  consdata->vars[v], bound) );
6353  }
6354 
6355  if( fixed )
6356  ++(*nfixedvars);
6357 
6358  break;
6359  }
6360 
6361  ++w;
6362  }
6363  }
6364 
6365  /* maybe last variable was the not infcheckvar */
6366  if( !foundvar )
6367  {
6368  assert(v == consdata->nvars - 1);
6369  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6370 
6371  if( consdata->vals[v] < 0 )
6372  {
6373  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6374  }
6375  else
6376  {
6377  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6378  }
6379 
6380  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6381  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6382  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6383 
6384  /* fix variable to only possible value */
6385  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6386  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6387 
6388  if( *cutoff )
6389  {
6390  /* start conflict analysis */
6391  /* @todo improve conflict analysis by adding relaxed bounds */
6392  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6393  consdata->vars[v], bound) );
6394  }
6395 
6396  if( fixed )
6397  ++(*nfixedvars);
6398  }
6399  }
6400  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6401  {
6402  /* aggregation possible if we have two variables, but this will be done later on */
6403  SCIP_CONS* newcons;
6404  char name[SCIP_MAXSTRLEN];
6405 
6406  /* create, add, and release new artificial constraint */
6407  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6408  ++conshdlrdata->naddconss;
6409 
6410  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6411 
6412  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6413  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6414  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6415 
6416  SCIPdebugPrintCons(scip, newcons, NULL);
6417 
6418  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6419 
6420  ++(*naddconss);
6421  }
6422  }
6423  }
6424  /* at least two solutions */
6425  else
6426  {
6427  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6428 
6429  /* only one variable in the second set, so we can bound this variables */
6430  if( ninfcheckvars == 1 )
6431  {
6432  SCIP_Bool tightened;
6433  SCIP_Real newlb;
6434  SCIP_Real newub;
6435 
6436  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6437 
6438  if( infcheckvals[0] < 0 )
6439  {
6440  newlb = maxvalue/infcheckvals[0];
6441  newub = minvalue/infcheckvals[0];
6442  }
6443  else
6444  {
6445  newlb = minvalue/infcheckvals[0];
6446  newub = maxvalue/infcheckvals[0];
6447  }
6448  assert(newlb < newub);
6449 
6450  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6451  {
6452  /* update lower bound of variable */
6453  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6454  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6455 
6456  /* tighten variable lower bound to minimal possible value */
6457  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6458  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6459 
6460  if( *cutoff )
6461  {
6462  /* start conflict analysis */
6463  /* @todo improve conflict analysis by adding relaxed bounds */
6464  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6465  }
6466 
6467  if( tightened )
6468  ++(*nchgbds);
6469  }
6470 
6471  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6472  {
6473  /* update upper bound of variable */
6474  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6475  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6476 
6477  /* tighten variable upper bound to maximal possible value */
6478  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6479  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6480 
6481  if( *cutoff )
6482  {
6483  /* start conflict analysis */
6484  /* @todo improve conflict analysis by adding relaxed bounds */
6485  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6486  }
6487 
6488  if( tightened )
6489  ++(*nchgbds);
6490  }
6491  }
6492  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6493  else if( ninfcheckvars == nunfixedvars - 1 )
6494  {
6495  SCIP_Bool foundvar = FALSE;
6496  SCIP_Bool tightened;
6497  SCIP_Real newlb;
6498  SCIP_Real newub;
6499  int w = 0;
6500 
6501  assert(ninfcheckvars > 0);
6502  assert(minvalue < maxvalue);
6503 
6504  /* find variable which is not an infcheckvar and fix it */
6505  for( v = 0; v < consdata->nvars - 1; ++v )
6506  {
6507  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6508  {
6509  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6510  {
6511 #ifndef NDEBUG
6512  int v2 = v + 1;
6513  int w2 = w;
6514 
6515  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6516 
6517  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6518  {
6519  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6520  continue;
6521 
6522  assert(consdata->vars[v2] == infcheckvars[w2]);
6523  ++w2;
6524  }
6525  assert(w2 == ninfcheckvars);
6526 #endif
6527 
6528  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6529  foundvar = TRUE;
6530 
6531  if( consdata->vals[v] < 0 )
6532  {
6533  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6534  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6535  }
6536  else
6537  {
6538  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6539  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6540  }
6541  assert(SCIPisLE(scip, newlb, newub));
6542 
6543  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6544  {
6545  /* update lower bound of variable */
6546  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6547  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6548 
6549  /* tighten variable lower bound to minimal possible value */
6550  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6551  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6552 
6553  if( *cutoff )
6554  {
6555  /* start conflict analysis */
6556  /* @todo improve conflict analysis by adding relaxed bounds */
6557  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6558  consdata->vars[v], newlb) );
6559  }
6560 
6561  if( tightened )
6562  ++(*nchgbds);
6563  }
6564 
6565  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6566  {
6567  /* update upper bound of variable */
6568  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6569  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6570 
6571  /* tighten variable upper bound to maximal possible value */
6572  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6573  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6574 
6575  if( *cutoff )
6576  {
6577  /* start conflict analysis */
6578  /* @todo improve conflict analysis by adding relaxed bounds */
6579  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6580  consdata->vars[v], newub) );
6581  }
6582 
6583  if( tightened )
6584  ++(*nchgbds);
6585  }
6586 
6587  break;
6588  }
6589 
6590  ++w;
6591  }
6592  }
6593 
6594  /* maybe last variable was the not infcheckvar */
6595  if( !foundvar )
6596  {
6597  assert(v == consdata->nvars - 1);
6598  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6599 
6600  if( consdata->vals[v] < 0 )
6601  {
6602  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6603  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6604  }
6605  else
6606  {
6607  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6608  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6609  }
6610  assert(SCIPisLE(scip, newlb, newub));
6611 
6612  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6613  {
6614  /* update lower bound of variable */
6615  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6616  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6617 
6618  /* tighten variable lower bound to minimal possible value */
6619  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6620  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6621 
6622  if( *cutoff )
6623  {
6624  /* start conflict analysis */
6625  /* @todo improve conflict analysis by adding relaxed bounds */
6626  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6627  }
6628 
6629  if( tightened )
6630  ++(*nchgbds);
6631  }
6632 
6633  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6634  {
6635  /* update upper bound of variable */
6636  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6637  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6638 
6639  /* tighten variable upper bound to maximal possible value */
6640  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6641  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6642 
6643  if( *cutoff )
6644  {
6645  /* start conflict analysis */
6646  /* @todo improve conflict analysis by adding relaxed bounds */
6647  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6648  }
6649 
6650  if( tightened )
6651  ++(*nchgbds);
6652  }
6653  }
6654  }
6655  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6656  * region for our infcheckvars, if possible
6657  */
6658  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6659  {
6660  SCIP_CONS* newcons;
6661  char name[SCIP_MAXSTRLEN];
6662  SCIP_Real newlhs;
6663  SCIP_Real newrhs;
6664 
6665  assert(maxvalue > minvalue);
6666 
6667  if( SCIPisGT(scip, minvalue, minactinfvars) )
6668  newlhs = minvalue;
6669  else
6670  newlhs = -SCIPinfinity(scip);
6671 
6672  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6673  newrhs = maxvalue;
6674  else
6675  newrhs = SCIPinfinity(scip);
6676 
6677  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6678  {
6679  /* create, add, and release new artificial constraint */
6680  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6681  ++conshdlrdata->naddconss;
6682 
6683  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6684 
6685  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6686  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6687  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6688 
6689  SCIPdebugPrintCons(scip, newcons, NULL);
6690  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6691 
6692  ++(*naddconss);
6693  }
6694  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6695  * should be maxvalue */
6696  }
6697  }
6698  }
6699  }
6700  else if( addartconss && ncontvars < ninfcheckvars )
6701  {
6702  SCIP_Real maxact = 0.0;
6703  SCIP_Real minact = 0.0;
6704  int w = 0;
6705 
6706  /* compute activities of non-infcheckvars */
6707  for( v = 0; v < consdata->nvars; ++v )
6708  {
6709  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6710  {
6711  ++w;
6712  continue;
6713  }
6714 
6715  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6716  {
6717  if( SCIPvarIsBinary(consdata->vars[v]) )
6718  {
6719  if( consdata->vals[v] > 0.0 )
6720  maxact += consdata->vals[v];
6721  else
6722  minact += consdata->vals[v];
6723  }
6724  else
6725  {
6726  SCIP_Real tmpval;
6727 
6728  assert(SCIPvarIsIntegral(consdata->vars[v]));
6729 
6730  if( consdata->vals[v] > 0.0 )
6731  {
6732  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6733 
6734  if( SCIPisHugeValue(scip, -tmpval) )
6735  break;
6736 
6737  minact += tmpval;
6738 
6739  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6740 
6741  if( SCIPisHugeValue(scip, tmpval) )
6742  break;
6743 
6744  maxact += tmpval;
6745  }
6746  else
6747  {
6748  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6749 
6750  if( SCIPisHugeValue(scip, -tmpval) )
6751  break;
6752 
6753  minact += tmpval;
6754 
6755  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6756 
6757  if( SCIPisHugeValue(scip, tmpval) )
6758  break;
6759 
6760  maxact += tmpval;
6761  }
6762  }
6763  }
6764  }
6765  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6766  {
6767  SCIP_CONS* newcons;
6768  char name[SCIP_MAXSTRLEN];
6769  SCIP_Real newlhs;
6770  SCIP_Real newrhs;
6771 
6772  assert(maxact > minact);
6773  assert(w == ninfcheckvars);
6774 
6775  newlhs = lhs - maxact;
6776  newrhs = rhs - minact;
6777  assert(newlhs < newrhs);
6778 
6779  /* create, add, and release new artificial constraint */
6780  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6781  ++conshdlrdata->naddconss;
6782 
6783  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6784 
6785  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6786  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6787  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6788 
6789  SCIPdebugPrintCons(scip, newcons, NULL);
6790  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6791 
6792  ++(*naddconss);
6793  }
6794  }
6795 
6796  TERMINATE:
6797  SCIPfreeBufferArray(scip, &infcheckvals);
6798  SCIPfreeBufferArray(scip, &infcheckvars);
6799 
6800  return SCIP_OKAY;
6801 }
6802 
6803 /** tightens bounds of a single variable due to activity bounds */
6804 static
6806  SCIP* scip, /**< SCIP data structure */
6807  SCIP_CONS* cons, /**< linear constraint */
6808  int pos, /**< position of the variable in the vars array */
6809  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6810  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6811  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6812  )
6813 {
6814  SCIP_CONSDATA* consdata;
6815  SCIP_VAR* var;
6816  SCIP_Real val;
6817  SCIP_Real lb;
6818  SCIP_Real ub;
6819  SCIP_Real minresactivity;
6820  SCIP_Real maxresactivity;
6821  SCIP_Real lhs;
6822  SCIP_Real rhs;
6823  SCIP_Bool infeasible;
6824  SCIP_Bool tightened;
6825  SCIP_Bool minisrelax;
6826  SCIP_Bool maxisrelax;
6827  SCIP_Bool isminsettoinfinity;
6828  SCIP_Bool ismaxsettoinfinity;
6829 
6830  assert(scip != NULL);
6831  assert(cons != NULL);
6832  assert(cutoff != NULL);
6833  assert(nchgbds != NULL);
6834 
6835  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6836  if( SCIPconsIsModifiable(cons) )
6837  return SCIP_OKAY;
6838 
6839  consdata = SCIPconsGetData(cons);
6840  assert(consdata != NULL);
6841  assert(0 <= pos && pos < consdata->nvars);
6842 
6843  *cutoff = FALSE;
6844 
6845  var = consdata->vars[pos];
6846 
6847  /* we cannot tighten bounds of multi-aggregated variables */
6849  return SCIP_OKAY;
6850 
6851  val = consdata->vals[pos];
6852  lhs = consdata->lhs;
6853  rhs = consdata->rhs;
6854  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6855  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6856  assert(var != NULL);
6857  assert(!SCIPisZero(scip, val));
6858  assert(!SCIPisInfinity(scip, lhs));
6859  assert(!SCIPisInfinity(scip, -rhs));
6860 
6861  lb = SCIPvarGetLbLocal(var);
6862  ub = SCIPvarGetUbLocal(var);
6863  assert(SCIPisLE(scip, lb, ub));
6864 
6865  if( val > 0.0 )
6866  {
6867  /* check, if we can tighten the variable's bounds */
6868  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6869  {
6870  SCIP_Real newub;
6871 
6872  newub = (rhs - minresactivity)/val;
6873 
6874  if( !SCIPisInfinity(scip, newub) &&
6875  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6876  {
6877  SCIP_Bool activityunreliable;
6878  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6879 
6880  /* check minresactivities for reliability */
6881  if( activityunreliable )
6882  {
6883  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6884  newub = (rhs - minresactivity)/val;
6885  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6886  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6887  && (!force || !SCIPisLT(scip, newub, ub)));
6888  }
6889 
6890  if( !activityunreliable )
6891  {
6892  /* tighten upper bound */
6893  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6894  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6895  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6896  &infeasible, &tightened) );
6897  if( infeasible )
6898  {
6899  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6900  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6901 
6902  /* analyze conflict */
6903  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6904 
6905  *cutoff = TRUE;
6906  return SCIP_OKAY;
6907  }
6908  if( tightened )
6909  {
6910  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6911  assert(SCIPisFeasLE(scip, ub, newub));
6912  (*nchgbds)++;
6913 
6914  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6915  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6916  }
6917  }
6918  }
6919  }
6920 
6921  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6922  {
6923  SCIP_Real newlb;
6924 
6925  newlb = (lhs - maxresactivity)/val;
6926  if( !SCIPisInfinity(scip, -newlb) &&
6927  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6928  {
6929  /* check maxresactivities for reliability */
6930  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6931  {
6932  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6933  newlb = (lhs - maxresactivity)/val;
6934 
6935  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6936  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6937  && (!force || !SCIPisGT(scip, newlb, lb))) )
6938  return SCIP_OKAY;
6939  }
6940 
6941  /* tighten lower bound */
6942  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6943  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6944  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6945  &infeasible, &tightened) );
6946  if( infeasible )
6947  {
6948  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6949  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6950 
6951  /* analyze conflict */
6952  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6953 
6954  *cutoff = TRUE;
6955  return SCIP_OKAY;
6956  }
6957  if( tightened )
6958  {
6959  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6960  assert(SCIPisFeasGE(scip, lb, newlb));
6961  (*nchgbds)++;
6962  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6963  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6964  }
6965  }
6966  }
6967  }
6968  else
6969  {
6970  /* check, if we can tighten the variable's bounds */
6971  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6972  {
6973  SCIP_Real newlb;
6974 
6975  newlb = (rhs - minresactivity)/val;
6976  if( !SCIPisInfinity(scip, -newlb) &&
6977  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6978  {
6979  SCIP_Bool activityunreliable;
6980  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6981  /* check minresactivities for reliability */
6982  if( activityunreliable )
6983  {
6984  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6985  newlb = (rhs - minresactivity)/val;
6986 
6987  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6988  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6989  && (!force || !SCIPisGT(scip, newlb, lb)));
6990  }
6991 
6992  if( !activityunreliable )
6993  {
6994  /* tighten lower bound */
6995  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6996  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6997  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6998  &infeasible, &tightened) );
6999  if( infeasible )
7000  {
7001  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7002  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
7003 
7004  /* analyze conflict */
7005  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7006 
7007  *cutoff = TRUE;
7008  return SCIP_OKAY;
7009  }
7010  if( tightened )
7011  {
7012  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7013  assert(SCIPisFeasGE(scip, lb, newlb));
7014  (*nchgbds)++;
7015  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7016  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7017  }
7018  }
7019  }
7020  }
7021 
7022  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7023  {
7024  SCIP_Real newub;
7025 
7026  newub = (lhs - maxresactivity)/val;
7027  if( !SCIPisInfinity(scip, newub) &&
7028  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7029  {
7030  /* check maxresactivities for reliability */
7031  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7032  {
7033  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7034  newub = (lhs - maxresactivity)/val;
7035 
7036  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7037  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7038  && (!force || !SCIPisLT(scip, newub, ub))) )
7039  return SCIP_OKAY;
7040  }
7041 
7042  /* tighten upper bound */
7043  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7044  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7045  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7046  &infeasible, &tightened) );
7047  if( infeasible )
7048  {
7049  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7050  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7051 
7052  /* analyze conflict */
7053  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7054 
7055  *cutoff = TRUE;
7056  return SCIP_OKAY;
7057  }
7058  if( tightened )
7059  {
7060  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7061  assert(SCIPisFeasLE(scip, ub, newub));
7062  (*nchgbds)++;
7063  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7064  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7065  }
7066  }
7067  }
7068  }
7069 
7070  return SCIP_OKAY;
7071 }
7072 
7073 #define MAXTIGHTENROUNDS 10
7074 
7075 /** tightens bounds of variables in constraint due to activity bounds */
7076 static
7078  SCIP* scip, /**< SCIP data structure */
7079  SCIP_CONS* cons, /**< linear constraint */
7080  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7081  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7082  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7083  int* nchgbds /**< pointer to count the total number of tightened bounds */
7084  )
7085 {
7086  SCIP_CONSDATA* consdata;
7087  unsigned int tightenmode;
7088  int nvars;
7089  int nrounds;
7090  int lastchange;
7091  int oldnchgbds;
7092 #ifndef SCIP_DEBUG
7093  int oldnchgbdstotal;
7094 #endif
7095  int v;
7096  SCIP_Bool force;
7097  SCIP_Bool easycase;
7098 
7099  assert(scip != NULL);
7100  assert(cons != NULL);
7101  assert(nchgbds != NULL);
7102  assert(cutoff != NULL);
7103 
7104  *cutoff = FALSE;
7105 
7106  /* we cannot tighten variables' bounds, if the constraint may be not complete */
7107  if( SCIPconsIsModifiable(cons) )
7108  return SCIP_OKAY;
7109 
7110  /* if a constraint was created after presolve, then it may hold fixed variables
7111  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7112  * thus, ensure here again that variable fixings have been applied
7113  */
7114  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7115  if( *cutoff )
7116  return SCIP_OKAY;
7117 
7118  /* check if constraint has any chances of tightening bounds */
7119  if( !canTightenBounds(cons) )
7120  return SCIP_OKAY;
7121 
7122  consdata = SCIPconsGetData(cons);
7123  assert(consdata != NULL);
7124 
7125  nvars = consdata->nvars;
7126  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7127 
7128  /* we are at the root node or during presolving */
7129  if( SCIPgetDepth(scip) < 1 )
7130  tightenmode = 2;
7131  else
7132  tightenmode = 1;
7133 
7134  /* stop if we already tightened the constraint and the tightening is not forced */
7135  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7136  return SCIP_OKAY;
7137 
7138  /* ensure that the variables are properly sorted */
7139  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7140  {
7141  SCIP_CALL( consdataSort(scip, consdata) );
7142  assert(consdata->coefsorted);
7143  }
7144 
7145  /* update maximal activity delta if necessary */
7146  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7147  consdataRecomputeMaxActivityDelta(scip, consdata);
7148 
7149  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7150  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7151  checkMaxActivityDelta(scip, consdata);
7152 
7153  /* this may happen if all variables are fixed */
7154  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7155  return SCIP_OKAY;
7156 
7157  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7158  {
7159  SCIP_Real slack;
7160  SCIP_Real surplus;
7161  SCIP_Real minactivity;
7162  SCIP_Real maxactivity;
7163  SCIP_Bool minisrelax;
7164  SCIP_Bool maxisrelax;
7165  SCIP_Bool isminsettoinfinity;
7166  SCIP_Bool ismaxsettoinfinity;
7167 
7168  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7169  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7170  &isminsettoinfinity, &ismaxsettoinfinity);
7171  assert(!SCIPisInfinity(scip, minactivity));
7172  assert(!SCIPisInfinity(scip, -maxactivity));
7173 
7174  slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7175  surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7176 
7177  /* check if the constraint will propagate */
7178  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7179  return SCIP_OKAY;
7180  }
7181 
7182  /* check if we can use fast implementation for easy and numerically well behaved cases */
7183  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7184 
7185  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7186  lastchange = -1;
7187  oldnchgbds = 0;
7188 
7189 #ifndef SCIP_DEBUG
7190  oldnchgbdstotal = *nchgbds;
7191 #endif
7192 
7193  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7194  {
7195  /* ensure that the variables are properly sorted
7196  *
7197  * note: it might happen that integer variables become binary during bound tightening at the root node
7198  */
7199  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7200  {
7201  SCIP_CALL( consdataSort(scip, consdata) );
7202  assert(consdata->coefsorted);
7203  }
7204 
7205  /* mark the constraint to have the variables' bounds tightened */
7206  consdata->boundstightened = (unsigned int)tightenmode;
7207 
7208  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7209  * sorting enables skipping variables
7210  */
7211  v = 0;
7212  while( v < nvars && v != lastchange && !(*cutoff) )
7213  {
7214  oldnchgbds = *nchgbds;
7215 
7216  if( easycase )
7217  {
7218  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7219  }
7220  else
7221  {
7222  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7223  }
7224 
7225  /* if there was no progress, skip the rest of the binary variables */
7226  if( *nchgbds > oldnchgbds )
7227  {
7228  lastchange = v;
7229  ++v;
7230  }
7231  else if( consdata->coefsorted && v < consdata->nbinvars - 1
7232  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7233  v = consdata->nbinvars;
7234  else
7235  ++v;
7236  }
7237 
7238 #ifndef SCIP_DEBUG
7239  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7240  *nchgbds - oldnchgbdstotal, nrounds);
7241  oldnchgbdstotal += oldnchgbds;
7242 #endif
7243  }
7244 
7245 #ifndef NDEBUG
7246  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7247  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7248 #endif
7249 
7250  return SCIP_OKAY;
7251 }
7252 
7253 /** checks linear constraint for feasibility of given solution or current solution */
7254 static
7256  SCIP* scip, /**< SCIP data structure */
7257  SCIP_CONS* cons, /**< linear constraint */
7258  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7259  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7260  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7261  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7262  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7263  )
7264 {
7265  SCIP_CONSDATA* consdata;
7266  SCIP_Real activity;
7267  SCIP_Real absviol;
7268  SCIP_Real relviol;
7269  SCIP_Real lhsviol;
7270  SCIP_Real rhsviol;
7271 
7272  assert(scip != NULL);
7273  assert(cons != NULL);
7274  assert(violated != NULL);
7275 
7276  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7277  SCIPdebugPrintCons(scip, cons, NULL);
7278 
7279  consdata = SCIPconsGetData(cons);
7280  assert(consdata != NULL);
7281 
7282  *violated = FALSE;
7283 
7284  if( consdata->row != NULL )
7285  {
7286  if( !checklprows && SCIProwIsInLP(consdata->row) )
7287  return SCIP_OKAY;
7288  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7289  activity = consdataComputePseudoActivity(scip, consdata);
7290  else
7291  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7292  }
7293  else
7294  activity = consdataGetActivity(scip, consdata, sol);
7295 
7296  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7297  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7298  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7299  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7300 
7301  /* calculate absolute and relative bound violations */
7302  lhsviol = consdata->lhs - activity;
7303  rhsviol = activity - consdata->rhs;
7304 
7305  absviol = 0.0;
7306  relviol = 0.0;
7307  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7308  {
7309  absviol = lhsviol;
7310  relviol = SCIPrelDiff(consdata->lhs, activity);
7311  }
7312  else if( rhsviol > 0 )
7313  {
7314  absviol = rhsviol;
7315  relviol = SCIPrelDiff(activity, consdata->rhs);
7316  }
7317 
7318  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7319  * return infeasible for safety
7320  */
7321  if( activity == SCIP_INVALID ) /*lint !e777*/
7322  {
7323  assert(sol == NULL);
7324  *violated = TRUE;
7325 
7326  /* set violation of invalid pseudo solutions */
7327  absviol = SCIP_INVALID;
7328  relviol = SCIP_INVALID;
7329 
7330  /* reset constraint age since we are in enforcement */
7331  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7332  }
7333  /* check with relative tolerances (the default) */
7334  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7335  {
7336  /* the "normal" check: one of the two sides is violated */
7337  if( !checkrelmaxabs )
7338  {
7339  *violated = TRUE;
7340 
7341  /* only reset constraint age if we are in enforcement */
7342  if( sol == NULL )
7343  {
7344  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7345  }
7346  }
7347  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7348  * small compared to the absolute values occurring in the activity
7349  */
7350  else
7351  {
7352  SCIP_Real maxabs;
7353  SCIP_Real coef;
7354  SCIP_Real absval;
7355  SCIP_Real solval;
7356  int v;
7357 
7358  maxabs = 1.0;
7359 
7360  /* compute maximum absolute value */
7361  for( v = 0; v < consdata->nvars; ++v )
7362  {
7363  if( consdata->vals != NULL )
7364  {
7365  coef = consdata->vals[v];
7366  }
7367  else
7368  coef = 1.0;
7369 
7370  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7371  absval = REALABS( coef * solval );
7372  maxabs = MAX( maxabs, absval );
7373  }
7374 
7375  /* regard left hand side, first */
7376  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7377  {
7378  /* check whether violation is random noise */
7379  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7380  {
7381  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7382  consdata->lhs - activity, maxabs);
7383  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7384 
7385  /* only increase constraint age if we are in enforcement */
7386  if( sol == NULL )
7387  {
7388  SCIP_CALL( SCIPincConsAge(scip, cons) );
7389  }
7390  }
7391  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7392  else if( SCIPisZero(scip, consdata->lhs) )
7393  {
7394  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7395  {
7396  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7397  consdata->lhs - activity, maxabs);
7398  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7399 
7400  /* only increase constraint age if we are in enforcement */
7401  if( sol == NULL )
7402  {
7403  SCIP_CALL( SCIPincConsAge(scip, cons) );
7404  }
7405  }
7406  else
7407  {
7408  *violated = TRUE;
7409 
7410  /* only reset constraint age if we are in enforcement */
7411  if( sol == NULL )
7412  {
7413  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7414  }
7415  }
7416  }
7417  else
7418  {
7419  *violated = TRUE;
7420 
7421  /* only reset constraint age if we are in enforcement */
7422  if( sol == NULL )
7423  {
7424  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7425  }
7426  }
7427  }
7428 
7429  /* now regard right hand side */
7430  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7431  {
7432  /* check whether violation is random noise */
7433  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7434  {
7435  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7436  activity - consdata->rhs, maxabs);
7437  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7438 
7439  /* only increase constraint age if we are in enforcement */
7440  if( sol == NULL )
7441  {
7442  SCIP_CALL( SCIPincConsAge(scip, cons) );
7443  }
7444  }
7445  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7446  else if( SCIPisZero(scip, consdata->rhs) )
7447  {
7448  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7449  {
7450  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7451  activity - consdata->rhs, maxabs);
7452  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7453 
7454  /* only increase constraint age if we are in enforcement */
7455  if( sol == NULL )
7456  {
7457  SCIP_CALL( SCIPincConsAge(scip, cons) );
7458  }
7459  }
7460  else
7461  {
7462  *violated = TRUE;
7463 
7464  /* only reset constraint age if we are in enforcement */
7465  if( sol == NULL )
7466  {
7467  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7468  }
7469  }
7470  }
7471  else
7472  {
7473  *violated = TRUE;
7474 
7475  /* only reset constraint age if we are in enforcement */
7476  if( sol == NULL )
7477  {
7478  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7479  }
7480  }
7481  }
7482  }
7483  }
7484  /* check with absolute tolerances */
7485  else if( consdata->checkabsolute &&
7486  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7487  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7488  {
7489  *violated = TRUE;
7490 
7491  /* only reset constraint age if we are in enforcement */
7492  if( sol == NULL )
7493  {
7494  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7495  }
7496  }
7497  else
7498  {
7499  /* only increase constraint age if we are in enforcement */
7500  if( sol == NULL )
7501  {
7502  SCIP_CALL( SCIPincConsAge(scip, cons) );
7503  }
7504  }
7505 
7506  /* update absolute and relative violation of the solution */
7507  if( sol != NULL )
7508  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7509 
7510  return SCIP_OKAY;
7511 }
7512 
7513 /** creates an LP row in a linear constraint data */
7514 static
7516  SCIP* scip, /**< SCIP data structure */
7517  SCIP_CONS* cons /**< linear constraint */
7518  )
7519 {
7520  SCIP_CONSDATA* consdata;
7521 
7522  assert(scip != NULL);
7523  assert(cons != NULL);
7524 
7525  consdata = SCIPconsGetData(cons);
7526  assert(consdata != NULL);
7527  assert(consdata->row == NULL);
7528 
7529  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7531 
7532  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7533 
7534  return SCIP_OKAY;
7535 }
7536 
7537 /** adds linear constraint as cut to the LP */
7538 static
7540  SCIP* scip, /**< SCIP data structure */
7541  SCIP_CONS* cons, /**< linear constraint */
7542  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7543  )
7544 {
7545  SCIP_CONSDATA* consdata;
7546 
7547  assert(scip != NULL);
7548  assert(cons != NULL);
7549 
7550  consdata = SCIPconsGetData(cons);
7551  assert(consdata != NULL);
7552 
7553  if( consdata->row == NULL )
7554  {
7555  if( !SCIPconsIsModifiable(cons) )
7556  {
7557  /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP
7558  * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7559  */
7560  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7561  if( *cutoff )
7562  return SCIP_OKAY;
7563  }
7564 
7565  /* convert consdata object into LP row */
7566  SCIP_CALL( createRow(scip, cons) );
7567  }
7568  assert(consdata->row != NULL);
7569 
7570  if( consdata->nvars == 0 )
7571  {
7572  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7573  }
7574 
7575  /* insert LP row as cut */
7576  if( !SCIProwIsInLP(consdata->row) )
7577  {
7578  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7579  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7580  /* if presolving is turned off, the row might be trivial */
7581  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7582  {
7583  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7584  }
7585 #ifndef NDEBUG
7586  else
7587  {
7588  int pr;
7589  int cr;
7590  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7591  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7592  assert( pr == 0 || cr == 0 );
7593  }
7594 #endif
7595  }
7596 
7597  return SCIP_OKAY;
7598 }
7599 
7600 /** adds linear constraint as row to the NLP, if not added yet */
7601 static
7603  SCIP* scip, /**< SCIP data structure */
7604  SCIP_CONS* cons /**< linear constraint */
7605  )
7606 {
7607  SCIP_CONSDATA* consdata;
7608 
7609  assert(SCIPisNLPConstructed(scip));
7610 
7611  /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7612  if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7613  return SCIP_OKAY;
7614 
7615  consdata = SCIPconsGetData(cons);
7616  assert(consdata != NULL);
7617 
7618  if( consdata->nlrow == NULL )
7619  {
7620  assert(consdata->lhs <= consdata->rhs);
7622  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7623  0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7624 
7625  assert(consdata->nlrow != NULL);
7626  }
7627 
7628  if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7629  {
7630  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7631  }
7632 
7633  return SCIP_OKAY;
7634 }
7635 
7636 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7637 static
7639  SCIP* scip, /**< SCIP data structure */
7640  SCIP_CONS* cons, /**< linear constraint */
7641  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7642  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7643  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7644  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7645  * the ones with non-zero dual value? */
7646  int* ncuts, /**< pointer to add up the number of found cuts */
7647  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7648  )
7649 {
7650  SCIP_CONSDATA* consdata;
7651  SCIP_Bool violated;
7652  int oldncuts;
7653 
7654  assert(scip != NULL);
7655  assert(conshdlrdata != NULL);
7656  assert(cons != NULL);
7657  assert(cutoff != NULL);
7658 
7659  consdata = SCIPconsGetData(cons);
7660  assert(ncuts != NULL);
7661  assert(consdata != NULL);
7662 
7663  oldncuts = *ncuts;
7664  *cutoff = FALSE;
7665 
7666  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7667 
7668  if( violated )
7669  {
7670  /* insert LP row as cut */
7671  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7672  (*ncuts)++;
7673  }
7674  else if( !SCIPconsIsModifiable(cons) && separatecards )
7675  {
7676  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7677  if( !separateall && sol == NULL )
7678  {
7679  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7680  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7681  {
7682  SCIP_Real dualsol;
7683 
7684  dualsol = SCIProwGetDualsol(consdata->row);
7685  if( SCIPisFeasNegative(scip, dualsol) )
7686  {
7687  if( !SCIPisInfinity(scip, consdata->rhs) )
7688  {
7689  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7690  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7691  }
7692  }
7693  else if( SCIPisFeasPositive(scip, dualsol) )
7694  {
7695  if( !SCIPisInfinity(scip, -consdata->lhs) )
7696  {
7697  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7698  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7699  }
7700  }
7701  }
7702  }
7703  else
7704  {
7705  if( !SCIPisInfinity(scip, consdata->rhs) )
7706  {
7707  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7708  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7709  }
7710  if( !SCIPisInfinity(scip, -consdata->lhs) )
7711  {
7712  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7713  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7714  }
7715  }
7716  }
7717 
7718  if( *ncuts > oldncuts )
7719  {
7720  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7721  }
7722 
7723  return SCIP_OKAY;
7724 }
7725 
7726 /** propagation method for linear constraints */
7727 static
7729  SCIP* scip, /**< SCIP data structure */
7730  SCIP_CONS* cons, /**< linear constraint */
7731  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7732  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7733  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7734  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7735  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7736  int* nchgbds /**< pointer to count the total number of tightened bounds */
7737  )
7738 {
7739  SCIP_CONSDATA* consdata;
7740  SCIP_Real minactivity;
7741  SCIP_Real maxactivity;
7742  SCIP_Bool minactisrelax;
7743  SCIP_Bool maxactisrelax;
7744  SCIP_Bool isminsettoinfinity;
7745  SCIP_Bool ismaxsettoinfinity;
7746 
7747  assert(scip != NULL);
7748  assert(cons != NULL);
7749  assert(cutoff != NULL);
7750  assert(nchgbds != NULL);
7751 
7752  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7753 
7754  consdata = SCIPconsGetData(cons);
7755  assert(consdata != NULL);
7756 
7757  if( consdata->eventdata == NULL )
7758  {
7759  SCIP_CONSHDLR* conshdlr;
7760  SCIP_CONSHDLRDATA* conshdlrdata;
7761 
7762  conshdlr = SCIPconsGetHdlr(cons);
7763  assert(conshdlr != NULL);
7764 
7765  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7766  assert(conshdlrdata != NULL);
7767 
7768  /* catch bound change events of variables */
7769  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7770  assert(consdata->eventdata != NULL);
7771  }
7772 
7773  *cutoff = FALSE;
7774 
7775  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7776  if( !SCIPconsIsModifiable(cons) )
7777  {
7778  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7779  if( !SCIPinRepropagation(scip) )
7780  {
7781  SCIP_CALL( SCIPincConsAge(scip, cons) );
7782  }
7783 
7784  /* tighten the variable's bounds */
7785  if( tightenbounds )
7786  {
7787  int oldnchgbds;
7788 
7789  oldnchgbds = *nchgbds;
7790 
7791  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7792 
7793  if( *nchgbds > oldnchgbds )
7794  {
7795  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7796  }
7797  }
7798 
7799  /* propagate ranged rows */
7800  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7801  {
7802  int nfixedvars;
7803  int naddconss;
7804  SCIPdebug( int oldnchgbds = *nchgbds; )
7805 
7806  nfixedvars = 0;
7807  naddconss = 0;
7808 
7809  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7810 
7811  if( *cutoff )
7812  {
7813  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7814  }
7815  else
7816  {
7817  SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7818  }
7819 
7820  if( nfixedvars > 0 )
7821  *nchgbds += 2*nfixedvars;
7822  } /*lint !e438*/
7823 
7824  /* check constraint for infeasibility and redundancy */
7825  if( !(*cutoff) )
7826  {
7827  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7828  &isminsettoinfinity, &ismaxsettoinfinity);
7829 
7830  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7831  {
7832  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7833  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7834 
7835  /* analyze conflict */
7836  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7837 
7838  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7839  *cutoff = TRUE;
7840  }
7841  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7842  {
7843  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7844  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7845 
7846  /* analyze conflict */
7847  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7848 
7849  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7850  *cutoff = TRUE;
7851  }
7852  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7853  {
7854  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7855  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7856 
7857  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7858  if( consdata->nvars > 0 )
7859  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7860  else
7861  SCIP_CALL( SCIPdelCons(scip, cons) );
7862  }
7863  }
7864  }
7865 
7866  return SCIP_OKAY;
7867 }
7868 
7869 
7870 /*
7871  * Presolving methods
7872  */
7873 
7874 /** converts all variables with fixed domain into FIXED variables */
7875 static
7877  SCIP* scip, /**< SCIP data structure */
7878  SCIP_CONS* cons, /**< linear constraint */
7879  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7880  int* nfixedvars /**< pointer to count the total number of fixed variables */
7881  )
7882 {
7883  SCIP_CONSDATA* consdata;
7884  SCIP_VAR* var;
7885  SCIP_VARSTATUS varstatus;
7886  SCIP_Real lb;
7887  SCIP_Real ub;
7888  SCIP_Bool fixed;
7889  SCIP_Bool infeasible;
7890  int v;
7891 
7892  assert(scip != NULL);
7893  assert(cons != NULL);
7894  assert(cutoff != NULL);
7895  assert(nfixedvars != NULL);
7896 
7897  consdata = SCIPconsGetData(cons);
7898  assert(consdata != NULL);
7899 
7900  for( v = 0; v < consdata->nvars; ++v )
7901  {
7902  assert(consdata->vars != NULL);
7903  var = consdata->vars[v];
7904  varstatus = SCIPvarGetStatus(var);
7905 
7906  if( varstatus != SCIP_VARSTATUS_FIXED )
7907  {
7908  lb = SCIPvarGetLbGlobal(var);
7909  ub = SCIPvarGetUbGlobal(var);
7910  if( SCIPisEQ(scip, lb, ub) )
7911  {
7912  SCIP_Real fixval;
7913 
7914  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7915  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7916  SCIPvarGetName(var), lb, ub, fixval);
7917  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7918  if( infeasible )
7919  {
7920  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7921  *cutoff = TRUE;
7922  return SCIP_OKAY;
7923  }
7924  if( fixed )
7925  (*nfixedvars)++;
7926  }
7927  }
7928  }
7929 
7930  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7931 
7932  if( infeasible )
7933  {
7934  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7935  *cutoff = TRUE;
7936  return SCIP_OKAY;
7937  }
7938 
7939  assert(consdata->removedfixings);
7940 
7941  return SCIP_OKAY;
7942 }
7943 
7944 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7945 
7946 /** extracts cliques of the constraint and adds them to SCIP
7947  *
7948  * The following clique extraction mechanism are implemeneted
7949  *
7950  * 1. collect binary variables and sort them in non increasing order, then
7951  *
7952  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7953  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7954  * condition
7955  *
7956  * minactivity + vals[i] + vals[i+1] > rhs
7957  *
7958  * and also add the binary to binary implication also for non-successive variables for which the same argument
7959  * holds
7960  *
7961  * minactivity + vals[i] + vals[j] > rhs
7962  *
7963  * 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
7964  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7965  *
7966  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7967  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7968  * condition
7969  *
7970  * maxactivity + vals[i] + vals[i-1] < lhs
7971  *
7972  * and also add the binary to binary implication also for non-successive variables for which the same argument
7973  * holds
7974  *
7975  * maxactivity + vals[i] + vals[j] < lhs
7976  *
7977  * e.g. you could multiply the above example by -1
7978  *
7979  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7980  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7981  * condition
7982  *
7983  * minactivity - vals[i] - vals[i-1] > rhs
7984  *
7985  * and also add the binary to binary implication also for non-successive variables for which the
7986  * same argument holds
7987  *
7988  * minactivity - vals[i] - vals[j] > rhs
7989  *
7990  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7991  * implication x1 = 0 => x3 = 1
7992  *
7993  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7994  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7995  * condition
7996  *
7997  * maxactivity - vals[i] - vals[i+1] < lhs
7998  *
7999  * and also add the binary to binary implication also for non-successive variables for which the same argument
8000  * holds
8001  *
8002  * maxactivity - vals[i] - vals[j] < lhs
8003  *
8004  * e.g. you could multiply the above example by -1
8005  *
8006  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8007  * as clique, (this part is done at the end of the method)
8008  *
8009  */
8010 static
8012  SCIP* scip, /**< SCIP data structure */
8013  SCIP_CONS* cons, /**< linear constraint */
8014  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8015  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8016  int* nfixedvars, /**< pointer to count number of fixed variables */
8017  int* nchgbds, /**< pointer to count the total number of tightened bounds */
8018  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8019  )
8020 {
8021  SCIP_VAR** vars;
8022  SCIP_Real* vals;
8023  SCIP_CONSDATA* consdata;
8024  SCIP_Bool lhsclique;
8025  SCIP_Bool rhsclique;
8026  SCIP_Bool finitelhs;
8027  SCIP_Bool finiterhs;
8028  SCIP_Bool finiteminact;
8029  SCIP_Bool finitemaxact;
8030  SCIP_Bool finitenegminact;
8031  SCIP_Bool finitenegmaxact;
8032  SCIP_Bool finiteposminact;
8033  SCIP_Bool finiteposmaxact;
8034  SCIP_Bool infeasible;
8035  SCIP_Bool stopped;
8036  int cliquenonzerosadded;
8037  int v;
8038  int i;
8039  int nposcoefs;
8040  int nnegcoefs;
8041  int nvars;
8042 
8043  assert(scip != NULL);
8044  assert(cons != NULL);
8045  assert(nfixedvars != NULL);
8046  assert(nchgbds != NULL);
8047  assert(cutoff != NULL);
8048  assert(!SCIPconsIsDeleted(cons));
8049 
8050  consdata = SCIPconsGetData(cons);
8051  assert(consdata != NULL);
8052 
8053  if( consdata->nvars < 2 )
8054  return SCIP_OKAY;
8055 
8056  /* add implications if posibble
8057  *
8058  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8059  * maximal absolute contribution and also only if this variable would force all other variables to their bound
8060  * corresponding to the global minimal activity of the constraint
8061  */
8062  if( !consdata->implsadded )
8063  {
8064  /* sort variables by variable type */
8065  SCIP_CALL( consdataSort(scip, consdata) );
8066 
8067  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8068  * up front, might change sorting correspondingly
8069  */
8070  /* fast abort if no binaries exist */
8071  if( !SCIPvarIsBinary(consdata->vars[0]) )
8072  {
8073 #ifndef NDEBUG
8074  for( i = 1; i < consdata->nvars; i++ )
8075  assert(!SCIPvarIsBinary(consdata->vars[i]));
8076 #endif
8077  return SCIP_OKAY;
8078  }
8079  nvars = consdata->nvars;
8080  vars = consdata->vars;
8081  vals = consdata->vals;
8082 
8083  /* recompute activities if needed */
8084  if( !consdata->validactivities )
8085  consdataCalcActivities(scip, consdata);
8086  assert(consdata->validactivities);
8087 
8088  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8089  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8090  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8091  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8092  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8093  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8094  finiteminact = (finitenegminact && finiteposminact);
8095  finitemaxact = (finitenegmaxact && finiteposmaxact);
8096 
8097  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8098  {
8099  SCIP_Real maxabscontrib = -1.0;
8100  SCIP_Bool posval = FALSE;
8101  SCIP_Bool allbinary = TRUE;
8102  int oldnchgbds = *nchgbds;
8103  int nbdchgs = 0;
8104  int nimpls = 0;
8105  int position = -1;
8106 
8107  /* we need a valid minimal/maximal activity to add cliques */
8108  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8109  {
8110  consdataRecomputeGlbMinactivity(scip, consdata);
8111  assert(consdata->validglbminact);
8112  }
8113 
8114  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8115  {
8116  consdataRecomputeGlbMaxactivity(scip, consdata);
8117  assert(consdata->validglbmaxact);
8118  }
8119  assert(consdata->validglbminact || consdata->validglbmaxact);
8120 
8121  /* @todo extend this to local/constraint probing */
8122 
8123  /* determine maximal contribution to the activity */
8124  for( v = nvars - 1; v >= 0; --v )
8125  {
8126  if( SCIPvarIsBinary(vars[v]) )
8127  {
8128  if( vals[v] > 0 )
8129  {
8130  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8131 
8132  if( value > maxabscontrib )
8133  {
8134  maxabscontrib = value;
8135  position = v;
8136  posval = TRUE;
8137  }
8138  }
8139  else
8140  {
8141  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8142 
8143  value = REALABS(value);
8144 
8145  if( value > maxabscontrib )
8146  {
8147  maxabscontrib = value;
8148  position = v;
8149  posval = FALSE;
8150  }
8151  }
8152  }
8153  else
8154  allbinary = FALSE;
8155  }
8156  assert(0 <= position && position < nvars);
8157 
8158  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8159  {
8160  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8161  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8162  * implications
8163  */
8164  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
8165  {
8166  for( v = nvars - 1; v >= 0; --v )
8167  {
8168  /* binary to binary implications will be collected when extrating cliques */
8169  if( !SCIPvarIsBinary(vars[v]) )
8170  {
8171  if( v != position )
8172  {
8173  if( vals[v] > 0 )
8174  {
8175  /* add implications */
8176  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8177  ++nimpls;
8178  *nchgbds += nbdchgs;
8179  }
8180  else
8181  {
8182  /* add implications */
8183  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8184  ++nimpls;
8185  *nchgbds += nbdchgs;
8186  }
8187 
8188  if( infeasible )
8189  {
8190  *cutoff = TRUE;
8191  break;
8192  }
8193  }
8194  }
8195  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8196  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8197  break;
8198  }
8199  }
8200 
8201  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8202  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8203  * implications
8204  */
8205  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
8206  {
8207  for( v = nvars - 1; v >= 0; --v )
8208  {
8209  /* binary to binary implications will be collected when extrating cliques */
8210  if( !SCIPvarIsBinary(vars[v]) )
8211  {
8212  if( v != position )
8213  {
8214  if( vals[v] > 0 )
8215  {
8216  /* add implications */
8217  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8218  ++nimpls;
8219  *nchgbds += nbdchgs;
8220  }
8221  else
8222  {
8223  /* add implications */
8224  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8225  ++nimpls;
8226  *nchgbds += nbdchgs;
8227  }
8228 
8229  if( infeasible )
8230  {
8231  *cutoff = TRUE;
8232  break;
8233  }
8234  }
8235  }
8236  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8237  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8238  break;
8239  }
8240  }
8241 
8242  /* did we find some implications */
8243  if( nimpls > 0 )
8244  {
8245  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8246 
8247  if( *cutoff )
8248  return SCIP_OKAY;
8249 
8250  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8251  if( *nchgbds - oldnchgbds > 0 )
8252  {
8253  /* check for fixed variables */
8254  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8255  if( *cutoff )
8256  return SCIP_OKAY;
8257 
8258  /* tighten variable's bounds */
8259  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8260  if( *cutoff )
8261  return SCIP_OKAY;
8262 
8263  /* check for fixed variables */
8264  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8265  if( *cutoff )
8266  return SCIP_OKAY;
8267  }
8268  }
8269  }
8270  }
8271 
8272  consdata->implsadded = TRUE;
8273  }
8274 
8275  /* check if we already added the cliques of this constraint */
8276  if( consdata->cliquesadded )
8277  return SCIP_OKAY;
8278 
8279  consdata->cliquesadded = TRUE;
8280  cliquenonzerosadded = 0;
8281  stopped = FALSE;
8282 
8283  /* sort variables by variable type */
8284  SCIP_CALL( consdataSort(scip, consdata) );
8285 
8286  nvars = consdata->nvars;
8287  vars = consdata->vars;
8288  vals = consdata->vals;
8289 
8290  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8291 
8292  /* recompute activities if needed */
8293  if( !consdata->validactivities )
8294  consdataCalcActivities(scip, consdata);
8295  assert(consdata->validactivities);
8296 
8297  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8298  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8299  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8300  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8301  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8302  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8303  finiteminact = (finitenegminact && finiteposminact);
8304  finitemaxact = (finitenegmaxact && finiteposmaxact);
8305 
8306  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8307  * information
8308  */
8309  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8310  {
8311  SCIP_VAR** binvars;
8312  SCIP_Real* binvarvals;
8313  int nposbinvars = 0;
8314  int nnegbinvars = 0;
8315  int allonebinary = 0;
8316 
8317  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8318  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8319 
8320  /* collect binary variables */
8321  for( i = 0; i < nvars; ++i )
8322  {
8323  if( SCIPvarIsBinary(vars[i]) )
8324  {
8325  assert(!SCIPisZero(scip, vals[i]));
8326 
8327  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8328  ++allonebinary;
8329 
8330  binvars[nposbinvars + nnegbinvars] = vars[i];
8331  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8332 
8333  if( SCIPisPositive(scip, vals[i]) )
8334  ++nposbinvars;
8335  else
8336  ++nnegbinvars;
8337 
8338  assert(nposbinvars + nnegbinvars <= nvars);
8339  }
8340  /* stop searching for binary variables, because the constraint data is sorted */
8341  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8342  break;
8343  }
8344  assert(nposbinvars + nnegbinvars <= nvars);
8345 
8346  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8347  * cliques
8348  */
8349  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8350  {
8351  SCIP_Real threshold;
8352  int oldnchgbds = *nchgbds;
8353  int nbdchgs;
8354  int jstart;
8355  int j;
8356 
8357  /* we need a valid minimal/maximal activity to add cliques */
8358  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8359  {
8360  consdataRecomputeGlbMinactivity(scip, consdata);
8361  assert(consdata->validglbminact);
8362  }
8363 
8364  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8365  {
8366  consdataRecomputeGlbMaxactivity(scip, consdata);
8367  assert(consdata->validglbmaxact);
8368  }
8369  assert(consdata->validglbminact || consdata->validglbmaxact);
8370 
8371  /* sort coefficients non-increasing to be faster in the clique search */
8372  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8373 
8374  /* case a) */
8375  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8376  {
8377  /* compute value that needs to be exceeded */
8378  threshold = consdata->rhs - consdata->glbminactivity;
8379 
8380  j = 1;
8381 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8382  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8383  assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8384 #endif
8385  /* check if at least two variables are in a clique */
8386  if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8387  {
8388  ++j;
8389  /* check for extending the clique */
8390  while( j < nposbinvars )
8391  {
8392  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8393  break;
8394  ++j;
8395  }
8396  assert(j >= 2);
8397 
8398  /* add clique with at least two variables */
8399  SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8400 
8401  if( infeasible )
8402  *cutoff = TRUE;
8403 
8404  *nchgbds += nbdchgs;
8405 
8406  cliquenonzerosadded += j;
8407  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8408  stopped = TRUE;
8409 
8410  /* exchange the last variable in the clique if possible and add all new ones */
8411  if( !stopped && !(*cutoff) && j < nposbinvars )
8412  {
8413  SCIP_VAR** clqvars;
8414  int lastfit = j - 2;
8415  assert(lastfit >= 0);
8416 
8417  /* copy all 'main'-clique variables */
8418  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8419 
8420  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8421  while( lastfit >= 0 && j < nposbinvars )
8422  {
8423  /* check if two variables are in a clique */
8424  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8425  {
8426  clqvars[lastfit + 1] = binvars[j];
8427 
8428  /* add clique with at least two variables */
8429  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8430 
8431  if( infeasible )
8432  {
8433  *cutoff = TRUE;
8434  break;
8435  }
8436 
8437  *nchgbds += nbdchgs;
8438 
8439  cliquenonzerosadded += (lastfit + 2);
8440  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8441  {
8442  stopped = TRUE;
8443  break;
8444  }
8445 
8446  ++j;
8447  }
8448  else
8449  --lastfit;
8450  }
8451 
8452  SCIPfreeBufferArray(scip, &clqvars);
8453  }
8454  }
8455  }
8456 
8457  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8458  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8459  {
8460  /* check for fixed variables */
8461  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8462 
8463  if( !*cutoff )
8464  {
8465  /* tighten variable's bounds */
8466  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8467 
8468  if( !*cutoff )
8469  {
8470  /* check for fixed variables */
8471  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8472 
8473  if( !*cutoff )
8474  {
8475  /* sort variables by variable type */
8476  SCIP_CALL( consdataSort(scip, consdata) );
8477 
8478  /* recompute activities if needed */
8479  if( !consdata->validactivities )
8480  consdataCalcActivities(scip, consdata);
8481  assert(consdata->validactivities);
8482 
8483  nvars = consdata->nvars;
8484  vars = consdata->vars;
8485  vals = consdata->vals;
8486  nposbinvars = 0;
8487  nnegbinvars = 0;
8488  allonebinary = 0;
8489 
8490  /* update binary variables */
8491  for( i = 0; i < nvars; ++i )
8492  {
8493  if( SCIPvarIsBinary(vars[i]) )
8494  {
8495  assert(!SCIPisZero(scip, vals[i]));
8496 
8497  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8498  ++allonebinary;
8499 
8500  binvars[nposbinvars + nnegbinvars] = vars[i];
8501  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8502 
8503  if( SCIPisPositive(scip, vals[i]) )
8504  ++nposbinvars;
8505  else
8506  ++nnegbinvars;
8507 
8508  assert(nposbinvars + nnegbinvars <= nvars);
8509  }
8510  /* stop searching for binary variables, because the constraint data is sorted */
8511  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8512  break;
8513  }
8514  assert(nposbinvars + nnegbinvars <= nvars);
8515  }
8516  }
8517  }
8518 
8519  oldnchgbds = *nchgbds;
8520  }
8521 
8522  /* case b) */
8523  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8524  {
8525  /* compute value that needs to be deceeded */
8526  threshold = consdata->lhs - consdata->glbmaxactivity;
8527 
8528  i = nposbinvars + nnegbinvars - 1;
8529  j = i - 1;
8530 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8531  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8532  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8533 #endif
8534  /* check if two variables are in a clique */
8535  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8536  {
8537  --j;
8538  /* check for extending the clique */
8539  while( j >= nposbinvars )
8540  {
8541  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8542  break;
8543  --j;
8544  }
8545  jstart = j;
8546 
8547  assert(i - j >= 2);
8548  /* add clique with at least two variables */
8549  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8550 
8551  if( infeasible )
8552  *cutoff = TRUE;
8553 
8554  *nchgbds += nbdchgs;
8555 
8556  cliquenonzerosadded += (i - j);
8557  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8558  stopped = TRUE;
8559 
8560  /* exchange the last variable in the clique if possible and add all new ones */
8561  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8562  {
8563  SCIP_VAR** clqvars;
8564  int lastfit = jstart + 1;
8565  assert(lastfit < i);
8566 
8567  /* copy all 'main'-clique variables */
8568  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8569  ++lastfit;
8570 
8571  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8572  while( lastfit <= i && j >= nposbinvars )
8573  {
8574  /* check if two variables are in a clique */
8575  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8576  {
8577  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8578  clqvars[lastfit - jstart - 2] = binvars[j];
8579 
8580  assert(i - lastfit + 2 >= 2);
8581  /* add clique with at least two variables */
8582  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8583 
8584  if( infeasible )
8585  {
8586  *cutoff = TRUE;
8587  break;
8588  }
8589 
8590  *nchgbds += nbdchgs;
8591 
8592  cliquenonzerosadded += (i - lastfit + 2);
8593  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8594  {
8595  stopped = TRUE;
8596  break;
8597  }
8598 
8599  --j;
8600  }
8601  else
8602  ++lastfit;
8603  }
8604 
8605  SCIPfreeBufferArray(scip, &clqvars);
8606  }
8607  }
8608  }
8609 
8610  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8611  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8612  {
8613  /* check for fixed variables */
8614  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8615 
8616  if( !*cutoff )
8617  {
8618  /* tighten variable's bounds */
8619  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8620 
8621  if( !*cutoff )
8622  {
8623  /* check for fixed variables */
8624  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8625 
8626  if( !*cutoff )
8627  {
8628  /* sort variables by variable type */
8629  SCIP_CALL( consdataSort(scip, consdata) );
8630 
8631  /* recompute activities if needed */
8632  if( !consdata->validactivities )
8633  consdataCalcActivities(scip, consdata);
8634  assert(consdata->validactivities);
8635 
8636  nvars = consdata->nvars;
8637  vars = consdata->vars;
8638  vals = consdata->vals;
8639  nposbinvars = 0;
8640  nnegbinvars = 0;
8641  allonebinary = 0;
8642 
8643  /* update binary variables */
8644  for( i = 0; i < nvars; ++i )
8645  {
8646  if( SCIPvarIsBinary(vars[i]) )
8647  {
8648  assert(!SCIPisZero(scip, vals[i]));
8649 
8650  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8651  ++allonebinary;
8652 
8653  binvars[nposbinvars + nnegbinvars] = vars[i];
8654  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8655 
8656  if( SCIPisPositive(scip, vals[i]) )
8657  ++nposbinvars;
8658  else
8659  ++nnegbinvars;
8660 
8661  assert(nposbinvars + nnegbinvars <= nvars);
8662  }
8663  /* stop searching for binary variables, because the constraint data is sorted */
8664  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8665  break;
8666  }
8667  assert(nposbinvars + nnegbinvars <= nvars);
8668  }
8669  }
8670  }
8671 
8672  oldnchgbds = *nchgbds;
8673  }
8674 
8675  /* case c) */
8676  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8677  {
8678  SCIP_Bool* values;
8679 
8680  /* initialize clique values array for adding a negated clique */
8681  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8682  BMSclearMemoryArray(values, nnegbinvars);
8683 
8684  /* compute value that needs to be exceeded */
8685  threshold = consdata->rhs - consdata->glbminactivity;
8686 
8687  i = nposbinvars + nnegbinvars - 1;
8688  j = i - 1;
8689 
8690 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8691  /* check if the variable should not have already been fixed to one */
8692  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8693 #endif
8694 
8695  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8696  {
8697  --j;
8698  /* check for extending the clique */
8699  while( j >= nposbinvars )
8700  {
8701  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8702  break;
8703  --j;
8704  }
8705  jstart = j;
8706 
8707  assert(i - j >= 2);
8708  /* add negated clique with at least two variables */
8709  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8710 
8711  if( infeasible )
8712  *cutoff = TRUE;
8713 
8714  *nchgbds += nbdchgs;
8715 
8716  cliquenonzerosadded += (i - j);
8717  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8718  stopped = TRUE;
8719 
8720  /* exchange the last variable in the clique if possible and add all new ones */
8721  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8722  {
8723  SCIP_VAR** clqvars;
8724  int lastfit = j + 1;
8725  assert(lastfit < i);
8726 
8727  /* copy all 'main'-clique variables */
8728  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8729  ++lastfit;
8730 
8731  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8732  while( lastfit <= i && j >= nposbinvars )
8733  {
8734  /* check if two variables are in a negated clique */
8735  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8736  {
8737  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8738  clqvars[lastfit - jstart - 2] = binvars[j];
8739 
8740  assert(i - lastfit + 2 >= 2);
8741  /* add clique with at least two variables */
8742  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8743 
8744  if( infeasible )
8745  {
8746  *cutoff = TRUE;
8747  break;
8748  }
8749 
8750  *nchgbds += nbdchgs;
8751 
8752  cliquenonzerosadded += (i - lastfit + 2);
8753  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8754  {
8755  stopped = TRUE;
8756  break;
8757  }
8758 
8759  --j;
8760  }
8761  else
8762  ++lastfit;
8763  }
8764 
8765  SCIPfreeBufferArray(scip, &clqvars);
8766  }
8767  }
8768 
8769  SCIPfreeBufferArray(scip, &values);
8770  }
8771 
8772  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8773  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8774  {
8775  /* check for fixed variables */
8776  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8777 
8778  if( !*cutoff )
8779  {
8780  /* tighten variable's bounds */
8781  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8782 
8783  if( !*cutoff )
8784  {
8785  /* check for fixed variables */
8786  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8787 
8788  if( !*cutoff )
8789  {
8790  /* sort variables by variable type */
8791  SCIP_CALL( consdataSort(scip, consdata) );
8792 
8793  /* recompute activities if needed */
8794  if( !consdata->validactivities )
8795  consdataCalcActivities(scip, consdata);
8796  assert(consdata->validactivities);
8797 
8798  nvars = consdata->nvars;
8799  vars = consdata->vars;
8800  vals = consdata->vals;
8801  nposbinvars = 0;
8802  nnegbinvars = 0;
8803  allonebinary = 0;
8804 
8805  /* update binary variables */
8806  for( i = 0; i < nvars; ++i )
8807  {
8808  if( SCIPvarIsBinary(vars[i]) )
8809  {
8810  assert(!SCIPisZero(scip, vals[i]));
8811 
8812  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8813  ++allonebinary;
8814 
8815  binvars[nposbinvars + nnegbinvars] = vars[i];
8816  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8817 
8818  if( SCIPisPositive(scip, vals[i]) )
8819  ++nposbinvars;
8820  else
8821  ++nnegbinvars;
8822 
8823  assert(nposbinvars + nnegbinvars <= nvars);
8824  }
8825  /* stop searching for binary variables, because the constraint data is sorted */
8826  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8827  break;
8828  }
8829  assert(nposbinvars + nnegbinvars <= nvars);
8830  }
8831  }
8832  }
8833  }
8834 
8835  /* case d) */
8836  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8837  {
8838  SCIP_Bool* values;
8839 
8840  /* initialize clique values array for adding a negated clique */
8841  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8842  BMSclearMemoryArray(values, nposbinvars);
8843 
8844  /* compute value that needs to be exceeded */
8845  threshold = consdata->lhs - consdata->glbmaxactivity;
8846 
8847  j = 1;
8848 
8849 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8850  /* check if the variable should not have already been fixed to one */
8851  assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8852 #endif
8853 
8854  if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8855  {
8856  ++j;
8857  /* check for extending the clique */
8858  while( j < nposbinvars )
8859  {
8860  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8861  break;
8862  ++j;
8863  }
8864  assert(j >= 2);
8865 
8866  /* add negated clique with at least two variables */
8867  SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8868 
8869  if( infeasible )
8870  *cutoff = TRUE;
8871 
8872  *nchgbds += nbdchgs;
8873 
8874  cliquenonzerosadded += j;
8875  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8876  stopped = TRUE;
8877 
8878  /* exchange the last variable in the clique if possible and add all new ones */
8879  if( !stopped && !(*cutoff) && j < nposbinvars )
8880  {
8881  SCIP_VAR** clqvars;
8882  int lastfit = j - 2;
8883  assert(lastfit >= 0);
8884 
8885  /* copy all 'main'-clique variables */
8886  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8887 
8888  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8889  while( lastfit >= 0 && j < nposbinvars )
8890  {
8891  /* check if two variables are in a negated clique */
8892  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8893  {
8894  clqvars[lastfit + 1] = binvars[j];
8895 
8896  /* add clique with at least two variables */
8897  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8898 
8899  if( infeasible )
8900  {
8901  *cutoff = TRUE;
8902  break;
8903  }
8904 
8905  *nchgbds += nbdchgs;
8906 
8907  cliquenonzerosadded += lastfit + 2;
8908  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8909  break;
8910 
8911  ++j;
8912  }
8913  else
8914  --lastfit;
8915  }
8916 
8917  SCIPfreeBufferArray(scip, &clqvars);
8918  }
8919  }
8920 
8921  SCIPfreeBufferArray(scip, &values);
8922  }
8923  }
8924 
8925  SCIPfreeBufferArray(scip, &binvarvals);
8926  SCIPfreeBufferArray(scip, &binvars);
8927 
8928  if( *cutoff )
8929  return SCIP_OKAY;
8930  }
8931 
8932  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8933 
8934  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8935  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8936  */
8937  nposcoefs = 0;
8938  nnegcoefs = 0;
8939  for( i = 0; i < nvars; ++i )
8940  {
8941  if( !SCIPvarIsBinary(vars[i]) )
8942  return SCIP_OKAY;
8943  else if( SCIPisEQ(scip, vals[i], +1.0) )
8944  nposcoefs++;
8945  else if( SCIPisEQ(scip, vals[i], -1.0) )
8946  nnegcoefs++;
8947  else
8948  return SCIP_OKAY;
8949  }
8950 
8951  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8952  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8953 
8954  if( lhsclique || rhsclique )
8955  {
8956  SCIP_Bool* values;
8957  int nbdchgs;
8958 
8959  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8960  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8961  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8962 
8963  for( i = 0; i < nvars; ++i )
8964  values[i] = (rhsclique == (vals[i] > 0.0));
8965 
8966  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8967 
8968  if( infeasible )
8969  *cutoff = TRUE;
8970 
8971  *nchgbds += nbdchgs;
8972  SCIPfreeBufferArray(scip, &values);
8973  }
8974 
8975  return SCIP_OKAY;
8976 }
8977 
8978 /** tightens left and right hand side of constraint due to integrality */
8979 static
8981  SCIP* scip, /**< SCIP data structure */
8982  SCIP_CONS* cons, /**< linear constraint */
8983  int* nchgsides, /**< pointer to count number of side changes */
8984  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8985  )
8986 {
8987  SCIP_CONSDATA* consdata;
8988  SCIP_Real newlhs;
8989  SCIP_Real newrhs;
8990  SCIP_Bool chglhs;
8991  SCIP_Bool chgrhs;
8992  SCIP_Bool integral;
8993  int i;
8994 
8995  assert(scip != NULL);
8996  assert(cons != NULL);
8997  assert(nchgsides != NULL);
8998  assert(infeasible != NULL);
9000  consdata = SCIPconsGetData(cons);
9001  assert(consdata != NULL);
9002 
9003  *infeasible = FALSE;
9004 
9005  chglhs = FALSE;
9006  chgrhs = FALSE;
9007  newlhs = -SCIPinfinity(scip);
9008  newrhs = SCIPinfinity(scip);
9009 
9010  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9011  {
9012  integral = TRUE;
9013  for( i = 0; i < consdata->nvars && integral; ++i )
9014  {
9015  integral = SCIPisIntegral(scip, consdata->vals[i])
9016  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9017  }
9018  if( integral )
9019  {
9020  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9021  {
9022  newlhs = SCIPfeasCeil(scip, consdata->lhs);
9023  chglhs = TRUE;
9024  }
9025  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9026  {
9027  newrhs = SCIPfeasFloor(scip, consdata->rhs);
9028  chgrhs = TRUE;
9029  }
9030 
9031  /* check whether rounding would lead to an unsatisfiable constraint */
9032  if( SCIPisGT(scip, newlhs, newrhs) )
9033  {
9034  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9035  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9036 
9037  *infeasible = TRUE;
9038  return SCIP_OKAY;
9039  }
9040 
9041  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9042  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9043 
9044  if( chglhs )
9045  {
9046  assert(!SCIPisInfinity(scip, -newlhs));
9047 
9048  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9049  if( !consdata->upgraded )
9050  (*nchgsides)++;
9051  }
9052  if( chgrhs )
9053  {
9054  assert(!SCIPisInfinity(scip, newrhs));
9055 
9056  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9057  if( !consdata->upgraded )
9058  (*nchgsides)++;
9059  }
9060  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9061  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9062  }
9063  }
9064 
9065  return SCIP_OKAY;
9066 }
9067 
9068 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9069  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9070  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9071  * (i) ai >= 0:
9072  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9073  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9074  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9075  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9076  * - change coefficients:
9077  * ai' := max(lhs - minact, maxact - rhs)
9078  * lhs' := lhs - (ai - ai')*li
9079  * rhs' := rhs - (ai - ai')*ui
9080  * (ii) ai < 0:
9081  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9082  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9083  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9084  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9085  * - change coefficients:
9086  * ai' := min(rhs - maxact, minact - lhs)
9087  * lhs' := lhs - (ai - ai')*ui
9088  * rhs' := rhs - (ai - ai')*li
9089  *
9090  * We further try to remove redundant variable from the constraint;
9091  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9092  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9093  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9094  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9095  * 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
9096  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9097  *
9098  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9099  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9100  */
9101 static
9103  SCIP* scip, /**< SCIP data structure */
9104  SCIP_CONS* cons, /**< linear constraint */
9105  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9106  int* nchgsides /**< pointer to count number of side changes */
9107  )
9108 {
9109  SCIP_CONSDATA* consdata;
9110  SCIP_VAR* var;
9111  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9112  * activity, ignoring the coefficients contributing with infinite value */
9113  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9114  * activity, ignoring the coefficients contributing with infinite value */
9115  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9116  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9117  SCIP_Bool isminsettoinfinity;
9118  SCIP_Bool ismaxsettoinfinity;
9119  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9120  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9121  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9122  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9123  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9124  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9125  SCIP_Real val;
9126  SCIP_Real newval;
9127  SCIP_Real newlhs;
9128  SCIP_Real newrhs;
9129  SCIP_Real lb;
9130  SCIP_Real ub;
9131  int i;
9132 
9133  assert(scip != NULL);
9134  assert(cons != NULL);
9135  assert(nchgcoefs != NULL);
9136  assert(nchgsides != NULL);
9137 
9138  consdata = SCIPconsGetData(cons);
9139  assert(consdata != NULL);
9140 
9141  /* @todo Is this still needed with automatic recomputation of activities? */
9142  /* if the maximal coefficient is too large, recompute the activities */
9143  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9144  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9145  {
9146  consdataRecomputeMinactivity(scip, consdata);
9147  consdataRecomputeMaxactivity(scip, consdata);
9148  }
9149 
9150  /* get the minimal and maximal activity of the constraint */
9151  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9152  &isminsettoinfinity, &ismaxsettoinfinity);
9153 
9154  minleftactivity = 0.0;
9155  maxleftactivity = 0.0;
9156 
9157  /* try to tighten each coefficient */
9158  i = 0;
9159  while( i < consdata->nvars )
9160  {
9161  var = consdata->vars[i];
9162 
9163  /* get coefficient and variable's bounds */
9164  lb = SCIPvarGetLbLocal(var);
9165  ub = SCIPvarGetUbLocal(var);
9166  val = consdata->vals[i];
9167  assert(!SCIPisZero(scip, val));
9168 
9169  /* check sign of coefficient */
9170  if( val >= 0.0 )
9171  {
9172  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9174  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9175  {
9176  /* change coefficients:
9177  * ai' := max(lhs - minact, maxact - rhs)
9178  * lhs' := lhs - (ai - ai')*li
9179  * rhs' := rhs - (ai - ai')*ui
9180  */
9181 
9182  lval = consdata->lhs - minactivity;
9183  rval = maxactivity - consdata->rhs;
9184 
9185  /* Try to avoid cancellation, if there are only two variables */
9186  if( consdata->nvars == 2 )
9187  {
9188  SCIP_Real otherval;
9189  otherval = consdata->vals[1-i];
9190 
9191  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9192  {
9193  lval = consdata->lhs - val*lb;
9194  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9195  }
9196 
9197  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9198  {
9199  rval = val*ub - consdata->rhs;
9200  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9201  }
9202  }
9203 
9204  newval = MAX(lval, rval);
9205  assert(SCIPisSumRelLE(scip, newval, val));
9206 
9207  /* Try to avoid cancellation in computation of lhs/rhs */
9208  newlhs = consdata->lhs - val * lb;
9209  newlhs += newval * lb;
9210  newrhs = consdata->rhs - val * ub;
9211  newrhs += newval * ub;
9212 
9213  if( !SCIPisSumRelEQ(scip, newval, val) )
9214  {
9215  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9216  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9217  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9218 
9219  /* update the coefficient and the activity bounds */
9220  if( SCIPisZero(scip, newval) )
9221  {
9222  SCIP_CALL( delCoefPos(scip, cons, i) );
9223  i--;
9224  }
9225  else
9226  {
9227  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9228  }
9229  (*nchgcoefs)++;
9230 
9231  /* get the new minimal and maximal activity of the constraint */
9232  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9233  &isminsettoinfinity, &ismaxsettoinfinity);
9234 
9235  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9236  {
9237  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9238 
9239  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9240  (*nchgsides)++;
9241  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9242  }
9243 
9244  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9245  {
9246  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9247 
9248  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9249  (*nchgsides)++;
9250  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9251  }
9252  }
9253  }
9254  else
9255  {
9256  if( !SCIPisInfinity(scip, -minleftactivity) )
9257  {
9258  assert(!SCIPisInfinity(scip, val));
9259  assert(!SCIPisInfinity(scip, lb));
9260  if( SCIPisInfinity(scip, -lb) )
9261  minleftactivity = -SCIPinfinity(scip);
9262  else
9263  minleftactivity += val * lb;
9264  }
9265 
9266  if( !SCIPisInfinity(scip, maxleftactivity) )
9267  {
9268  assert(!SCIPisInfinity(scip, val));
9269  assert(!SCIPisInfinity(scip, -ub));
9270  if( SCIPisInfinity(scip,ub) )
9271  maxleftactivity = SCIPinfinity(scip);
9272  else
9273  maxleftactivity += val * ub;
9274  }
9275  }
9276  }
9277  else
9278  {
9279  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9281  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9282  {
9283  /* change coefficients:
9284  * ai' := min(rhs - maxact, minact - lhs)
9285  * lhs' := lhs - (ai - ai')*ui
9286  * rhs' := rhs - (ai - ai')*li
9287  */
9288 
9289  lval = minactivity - consdata->lhs;
9290  rval = consdata->rhs - maxactivity;
9291 
9292  /* Try to avoid cancellation, if there are only two variables */
9293  if( consdata->nvars == 2 )
9294  {
9295  SCIP_Real otherval;
9296  otherval = consdata->vals[1-i];
9297 
9298  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9299  {
9300  lval = val*ub - consdata->lhs;
9301  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9302  }
9303 
9304  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9305  {
9306  rval = consdata->rhs - val*lb;
9307  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9308  }
9309  }
9310 
9311  newval = MIN(lval, rval);
9312  assert(SCIPisSumRelGE(scip, newval, val));
9313 
9314  /* Try to avoid cancellation in computation of lhs/rhs */
9315  newlhs = consdata->lhs - val * ub;
9316  newlhs += newval * ub;
9317  newrhs = consdata->rhs - val * lb;
9318  newrhs += newval * lb;
9319 
9320  if( !SCIPisSumRelEQ(scip, newval, val) )
9321  {
9322  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9323  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9324  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9325 
9326  /* update the coefficient and the activity bounds */
9327  if( SCIPisZero(scip, newval) )
9328  {
9329  SCIP_CALL( delCoefPos(scip, cons, i) );
9330  i--;
9331  }
9332  else
9333  {
9334  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9335  }
9336  (*nchgcoefs)++;
9337 
9338  /* get the new minimal and maximal activity of the constraint */
9339  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9340  &isminsettoinfinity, &ismaxsettoinfinity);
9341 
9342  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9343  {
9344  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9345 
9346  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9347  (*nchgsides)++;
9348  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9349  }
9350 
9351  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9352  {
9353  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9354 
9355  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9356  (*nchgsides)++;
9357  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9358  }
9359  }
9360  }
9361  else
9362  {
9363  if( !SCIPisInfinity(scip, -minleftactivity) )
9364  {
9365  assert(!SCIPisInfinity(scip, -val));
9366  assert(!SCIPisInfinity(scip, -ub));
9367  if( SCIPisInfinity(scip, ub) )
9368  minleftactivity = -SCIPinfinity(scip);
9369  else
9370  minleftactivity += val * ub;
9371  }
9372 
9373  if( !SCIPisInfinity(scip, maxleftactivity) )
9374  {
9375  assert(!SCIPisInfinity(scip, -val));
9376  assert(!SCIPisInfinity(scip, lb));
9377  if( SCIPisInfinity(scip, -lb) )
9378  maxleftactivity = SCIPinfinity(scip);
9379  else
9380  maxleftactivity += val * lb;
9381  }
9382  }
9383  }
9384  ++i;
9385  }
9386 
9387  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9388  minleftactivity, consdata->rhs);
9389  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9390  maxleftactivity, consdata->lhs);
9391 
9392  /* minleft == \infty ==> minactivity == \infty */
9393  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9394  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9395 
9396  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9397  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9398  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9399  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9400  */
9401  assert(!SCIPisInfinity(scip, minactivity));
9402  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9403  return SCIP_OKAY;
9404 
9405  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9406  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9407  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9408  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9409  */
9410  assert(!SCIPisInfinity(scip, -maxactivity));
9411  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9412  return SCIP_OKAY;
9413 
9414  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9415  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9416  */
9417  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9418  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9419 
9420  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9421  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9422  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9423  * they can be removed from the constraint.
9424  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9425  */
9426  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisLT(scip, maxleftactivity, aggrlhs))
9427  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisGT(scip, minleftactivity, aggrrhs)) )
9428  {
9429  SCIP_Real minleftactivitypart;
9430  SCIP_Real maxleftactivitypart;
9431 
9432  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9433 
9434  /* try to remove redundant variables from constraint */
9435  i = 0;
9436  while( i < consdata->nvars )
9437  {
9438  var = consdata->vars[i];
9439  minleftactivitypart = 0.0;
9440  maxleftactivitypart = 0.0;
9441  lb = SCIPvarGetLbLocal(var);
9442  ub = SCIPvarGetUbLocal(var);
9443 
9444  /* get coefficient and variable's bounds */
9445  val = consdata->vals[i];
9446  assert(!SCIPisZero(scip, val));
9447 
9448  /* check sign of coefficient */
9449  if( val >= 0.0 )
9450  {
9451  /* negation of condition above in case of positive val */
9453  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9454  {
9455  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9456  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9457  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9458  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9459 
9460  minleftactivitypart = val * lb;
9461  maxleftactivitypart = val * ub;
9462 
9463  SCIP_CALL( delCoefPos(scip, cons, i) );
9464  i--;
9465 
9466  /* get the new minimal and maximal activity of the constraint */
9467  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9468  &isminsettoinfinity, &ismaxsettoinfinity);
9469 
9470  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9471  * huge contributions
9472  */
9473  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9474  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9475  }
9476  }
9477  else
9478  {
9479  /* negation of condition above in case of negative val */
9481  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9482  {
9483  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9484  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9485 
9486  minleftactivitypart = val * ub;
9487  maxleftactivitypart = val * lb;
9488 
9489  SCIP_CALL( delCoefPos(scip, cons, i) );
9490  i--;
9491 
9492  /* get the new minimal and maximal activity of the constraint */
9493  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9494  &isminsettoinfinity, &ismaxsettoinfinity);
9495 
9496  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9497  * huge contributions
9498  */
9499  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9500  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9501  }
9502  }
9503 
9504  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9505  * redundant variables could get deleted,
9506  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9507  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9508  * we would also delete y2 and as a result we would have gotten infeasibility */
9509  /* adjust lhs and right hand side */
9510  newlhs = consdata->lhs - minleftactivitypart;
9511  newrhs = consdata->rhs - maxleftactivitypart;
9512 
9513  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9514  {
9515  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9516  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9517  ++(*nchgsides);
9518  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9519  }
9520  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9521  {
9522  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9523  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9524  ++(*nchgsides);
9525  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9526  }
9527  ++i;
9528  }
9529  }
9530 
9531  return SCIP_OKAY;
9532 }
9533 
9534 /** processes equality with only one variable by fixing the variable and deleting the constraint */
9535 static
9537  SCIP* scip, /**< SCIP data structure */
9538  SCIP_CONS* cons, /**< linear constraint */
9539  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9540  int* nfixedvars, /**< pointer to count number of fixed variables */
9541  int* ndelconss /**< pointer to count number of deleted constraints */
9542  )
9543 {
9544  SCIP_CONSDATA* consdata;
9545  SCIP_VAR* var;
9546  SCIP_Real val;
9547  SCIP_Real fixval;
9548  SCIP_Bool infeasible;
9549  SCIP_Bool fixed;
9550 
9551  assert(scip != NULL);
9552  assert(cons != NULL);
9553  assert(cutoff != NULL);
9554  assert(nfixedvars != NULL);
9555  assert(ndelconss != NULL);
9556 
9557  consdata = SCIPconsGetData(cons);
9558  assert(consdata != NULL);
9559  assert(consdata->nvars == 1);
9560  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9561 
9562  /* calculate the value to fix the variable to */
9563  var = consdata->vars[0];
9564  val = consdata->vals[0];
9565  assert(!SCIPisZero(scip, val));
9566  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9567  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9568  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9569  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9570 
9571  /* fix variable */
9572  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9573  if( infeasible )
9574  {
9575  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9576  *cutoff = TRUE;
9577  return SCIP_OKAY;
9578  }
9579  if( fixed )
9580  (*nfixedvars)++;
9581 
9582  /* disable constraint */
9583  SCIP_CALL( SCIPdelCons(scip, cons) );
9584  if( !consdata->upgraded )
9585  (*ndelconss)++;
9586 
9587  return SCIP_OKAY;
9588 }
9589 
9590 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9591 static
9593  SCIP* scip, /**< SCIP data structure */
9594  SCIP_CONS* cons, /**< linear constraint */
9595  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9596  int* naggrvars, /**< pointer to count number of aggregated variables */
9597  int* ndelconss /**< pointer to count number of deleted constraints */
9598  )
9599 {
9600  SCIP_CONSDATA* consdata;
9601  SCIP_Bool infeasible;
9602  SCIP_Bool redundant;
9603  SCIP_Bool aggregated;
9604 
9605  assert(scip != NULL);
9606  assert(cons != NULL);
9607  assert(cutoff != NULL);
9608  assert(naggrvars != NULL);
9609  assert(ndelconss != NULL);
9610 
9611  consdata = SCIPconsGetData(cons);
9612  assert(consdata != NULL);
9613  assert(consdata->nvars == 2);
9614  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9615 
9616  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9617  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9618  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9619 
9620  /* aggregate the equality */
9621  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9622  consdata->rhs, &infeasible, &redundant, &aggregated) );
9623 
9624  /* check for infeasibility of aggregation */
9625  if( infeasible )
9626  {
9627  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9628  *cutoff = TRUE;
9629  return SCIP_OKAY;
9630  }
9631 
9632  /* count the aggregation */
9633  if( aggregated )
9634  (*naggrvars)++;
9635 
9636  /* delete the constraint, if it is redundant */
9637  if( redundant )
9638  {
9639  SCIP_CALL( SCIPdelCons(scip, cons) );
9640 
9641  if( !consdata->upgraded )
9642  (*ndelconss)++;
9643  }
9644 
9645  return SCIP_OKAY;
9646 }
9647 
9648 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9649 static
9651  SCIP* scip, /**< SCIP data structure */
9652  SCIP_CONSDATA* consdata, /**< linear constraint data */
9653  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9654  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9655  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9656  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9657  )
9658 {
9659  SCIP_Real slackvarlb;
9660  SCIP_Real slackvarub;
9661 
9662  assert(scip != NULL);
9663  assert(consdata != NULL);
9664  assert(newlhs != NULL);
9665  assert(newrhs != NULL);
9666  assert(!SCIPisInfinity(scip, -consdata->lhs));
9667  assert(!SCIPisInfinity(scip, consdata->rhs));
9668 
9669  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9670  slackvarub = SCIPvarGetUbGlobal(slackvar);
9671  if( slackcoef > 0.0 )
9672  {
9673  if( SCIPisInfinity(scip, -slackvarlb) )
9674  *newrhs = SCIPinfinity(scip);
9675  else
9676  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9677  if( SCIPisInfinity(scip, slackvarub) )
9678  *newlhs = -SCIPinfinity(scip);
9679  else
9680  *newlhs = consdata->lhs - slackcoef * slackvarub;
9681  }
9682  else
9683  {
9684  if( SCIPisInfinity(scip, -slackvarlb) )
9685  *newlhs = -SCIPinfinity(scip);
9686  else
9687  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9688  if( SCIPisInfinity(scip, slackvarub) )
9689  *newrhs = SCIPinfinity(scip);
9690  else
9691  *newrhs = consdata->lhs - slackcoef * slackvarub;
9692  }
9693  assert(SCIPisLE(scip, *newlhs, *newrhs));
9694 }
9695 
9696 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9697  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9698  * is implicitly integral by this constraint
9699  *
9700  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9701  * can help.
9702  */
9703 static
9705  SCIP* scip, /**< SCIP data structure */
9706  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9707  SCIP_CONS* cons, /**< linear constraint */
9708  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9709  int* naggrvars, /**< pointer to count number of aggregated variables */
9710  int* ndelconss /**< pointer to count number of deleted constraints */
9711  )
9712 {
9713  SCIP_CONSDATA* consdata;
9714  SCIP_VAR** vars;
9715  SCIP_Real* vals;
9716  SCIP_VARTYPE bestslacktype;
9717  SCIP_VARTYPE slacktype;
9718  SCIP_Real lhs;
9719  SCIP_Real rhs;
9720  SCIP_Real bestslackdomrng;
9721  SCIP_Real minabsval;
9722  SCIP_Real maxabsval;
9723  SCIP_Bool bestremovescons;
9724  SCIP_Bool coefszeroone;
9725  SCIP_Bool coefsintegral;
9726  SCIP_Bool varsintegral;
9727  SCIP_Bool infeasible;
9728  SCIP_Bool samevar;
9729  int supinf; /* counter for infinite contributions to the supremum of a possible
9730  * multi-aggregation
9731  */
9732  int infinf; /* counter for infinite contributions to the infimum of a possible
9733  * multi-aggregation
9734  */
9735  int maxnlocksstay;
9736  int maxnlocksremove;
9737  int bestslackpos;
9738  int bestnlocks;
9739  int ncontvars;
9740  int contvarpos;
9741  int nintvars;
9742  int nimplvars;
9743  int intvarpos;
9744  int v;
9745 
9746  assert(scip != NULL);
9747  assert(cons != NULL);
9748  assert(cutoff != NULL);
9749  assert(naggrvars != NULL);
9750 
9751  consdata = SCIPconsGetData(cons);
9752  assert(consdata != NULL);
9753  assert(consdata->nvars > 2);
9754  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9755 
9756  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9757 
9758  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9759  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9760  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9761  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9762  */
9763  lhs = consdata->lhs;
9764  rhs = consdata->rhs;
9765  maxnlocksstay = 0;
9766  if( consdata->nvars == 3 )
9767  {
9768  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9769  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9770  */
9771  maxnlocksremove = 3;
9772  }
9773  else if( consdata->nvars == 4 )
9774  {
9775  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9776  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9777  */
9778  maxnlocksremove = 2;
9779  }
9780  else
9781  {
9782  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9783  maxnlocksremove = 1;
9784  }
9785 
9786  /* the locks on this constraint can be ignored */
9787  if( SCIPconsIsChecked(cons) )
9788  {
9789  if( !SCIPisInfinity(scip, -lhs) )
9790  {
9791  maxnlocksstay++;
9792  maxnlocksremove++;
9793  }
9794  if( !SCIPisInfinity(scip, rhs) )
9795  {
9796  maxnlocksstay++;
9797  maxnlocksremove++;
9798  }
9799  }
9800 
9801  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9802  vars = consdata->vars;
9803  vals = consdata->vals;
9804  bestslackpos = -1;
9805  bestslacktype = SCIP_VARTYPE_BINARY;
9806  bestnlocks = INT_MAX;
9807  bestremovescons = FALSE;
9808  bestslackdomrng = 0.0;
9809  coefszeroone = TRUE;
9810  coefsintegral = TRUE;
9811  varsintegral = TRUE;
9812  ncontvars = 0;
9813  contvarpos = -1;
9814  nintvars = 0;
9815  nimplvars = 0;
9816  intvarpos = -1;
9817  minabsval = SCIPinfinity(scip);
9818  maxabsval = -1.0;
9819  for( v = 0; v < consdata->nvars; ++v )
9820  {
9821  SCIP_VAR* var;
9822  SCIP_Real val;
9823  SCIP_Real absval;
9824  SCIP_Real varlb;
9825  SCIP_Real varub;
9826  SCIP_Bool iscont;
9827  int nlocks;
9828 
9829  assert(vars != NULL);
9830  assert(vals != NULL);
9831 
9832  var = vars[v];
9833  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9834  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9835  varlb = SCIPvarGetLbGlobal(var);
9836  varub = SCIPvarGetUbGlobal(var);
9837 
9838  val = vals[v];
9839  absval = REALABS(val);
9840  assert(SCIPisPositive(scip, absval));
9841 
9842  /* calculate minimal and maximal absolute value */
9843  if( absval < minabsval )
9844  minabsval = absval;
9845  if( absval > maxabsval )
9846  maxabsval = absval;
9847 
9848  /* do not try to multi aggregate, when numerical bad */
9849  if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9850  return SCIP_OKAY;
9851 
9852  slacktype = SCIPvarGetType(var);
9853  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9854  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9855  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9856  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9857 
9858  /* update candidates for continuous -> implint and integer -> implint conversion */
9859  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9860  {
9861  ncontvars++;
9862  contvarpos = v;
9863  }
9864  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9865  {
9866  ++nimplvars;
9867  }
9868  else if( slacktype == SCIP_VARTYPE_INTEGER )
9869  {
9870  nintvars++;
9871  intvarpos = v;
9872  }
9873 
9874  /* check, if variable is already fixed or aggregated */
9875  if( !SCIPvarIsActive(var) )
9876  continue;
9877 
9878  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9880 
9881  if( nlocks > maxnlocksremove )
9882  continue;
9883 
9884  /* check, if variable can be used as a slack variable */
9885  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9886  !SCIPdoNotMultaggrVar(scip, var) )
9887  {
9888  SCIP_Bool better;
9889  SCIP_Bool equal;
9890  SCIP_Real slackdomrng;
9891 
9892  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9893  slackdomrng = SCIPinfinity(scip);
9894  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9895  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9896  return SCIP_OKAY;
9897  else
9898  {
9899  slackdomrng = (varub - varlb)*absval;
9900  assert(!SCIPisInfinity(scip, slackdomrng));
9901  }
9902  equal = FALSE;
9903  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9904  if( !better && slacktype == bestslacktype )
9905  {
9906  better = (nlocks < bestnlocks);
9907  if( nlocks == bestnlocks && !bestremovescons )
9908  {
9909  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9910  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9911  }
9912  }
9913 
9914  if( better || equal )
9915  {
9916  SCIP_Real minresactivity;
9917  SCIP_Real maxresactivity;
9918  SCIP_Real newlhs;
9919  SCIP_Real newrhs;
9920  SCIP_Bool removescons;
9921  SCIP_Bool minisrelax;
9922  SCIP_Bool maxisrelax;
9923  SCIP_Bool isminsettoinfinity;
9924  SCIP_Bool ismaxsettoinfinity;
9925 
9926  /* check if the constraint becomes redundant after multi-aggregation */
9927  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9928  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9929 
9930  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9931  * activity
9932  */
9933  if( minisrelax || maxisrelax )
9934  continue;
9935 
9936  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9937  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9938 
9939  /* check resactivities for reliability */
9940  if( removescons )
9941  {
9942  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9943  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9944 
9945  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9946  && SCIPisFeasLE(scip, newlhs, minresactivity))
9947  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9948 
9949  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9950  }
9951 
9952  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9953  if( conshdlrdata->multaggrremove && !removescons )
9954  continue;
9955 
9956  /* prefer variables that make the constraints redundant */
9957  if( bestremovescons && !removescons )
9958  continue;
9959 
9960  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9961  * other constraints
9962  */
9963  if( !removescons && nlocks > maxnlocksstay )
9964  continue;
9965 
9966  better = better || (!bestremovescons && removescons);
9967  if( better )
9968  {
9969  bestslackpos = v;
9970  bestslacktype = slacktype;
9971  bestnlocks = nlocks;
9972  bestslackdomrng = slackdomrng;
9973  bestremovescons = removescons;
9974  }
9975  }
9976  }
9977  }
9978 
9979  /* if all coefficients and variables are integral, the right hand side must also be integral */
9980  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9981  {
9982  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9983  SCIPdebugPrintCons(scip, cons, NULL);
9984  *cutoff = TRUE;
9985  return SCIP_OKAY;
9986  }
9987 
9988  supinf = 0;
9989  infinf = 0;
9990  samevar = FALSE;
9991 
9992  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9993  for( v = 0; v < consdata->nvars; ++v )
9994  {
9995  if( v != bestslackpos )
9996  {
9997  if( SCIPisPositive(scip, consdata->vals[v]) )
9998  {
9999  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10000  {
10001  ++supinf;
10002  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10003  {
10004  ++infinf;
10005  samevar = TRUE;
10006  }
10007  }
10008  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10009  ++infinf;
10010  }
10011  else if( SCIPisNegative(scip, consdata->vals[v]) )
10012  {
10013  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10014  {
10015  ++supinf;
10016  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10017  {
10018  ++infinf;
10019  samevar = TRUE;
10020  }
10021  }
10022  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10023  ++infinf;
10024  }
10025  }
10026  }
10027  assert(!samevar || (supinf > 0 && infinf > 0));
10028 
10029  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10030  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10031  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10032  {
10033  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10034  return SCIP_OKAY;
10035  }
10036 
10037  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10038  * we cannot aggregate the variable, because the integrality condition would get lost
10039  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10040  * loose the integrality condition for this variable.
10041  */
10042  if( bestslackpos >= 0
10043  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
10044  || (coefsintegral && varsintegral && nimplvars == 0)) )
10045  {
10046  SCIP_VAR* slackvar;
10047  SCIP_Real* scalars;
10048  SCIP_Real slackcoef;
10049  SCIP_Real aggrconst;
10050  SCIP_Real newlhs;
10051  SCIP_Real newrhs;
10052  SCIP_Bool aggregated;
10053 
10054  /* we found a slack variable that only occurs in at most one other constraint:
10055  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10056  */
10057  assert(bestslackpos < consdata->nvars);
10058 
10059  /* do not multi aggregate binary variables */
10060  if( SCIPvarIsBinary(vars[bestslackpos]) )
10061  return SCIP_OKAY;
10062 
10063  /* convert equality into inequality by deleting the slack variable:
10064  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10065  */
10066  slackvar = vars[bestslackpos];
10067  slackcoef = vals[bestslackpos];
10068  assert(!SCIPisZero(scip, slackcoef));
10069  aggrconst = consdata->rhs/slackcoef;
10070 
10071  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10072  assert(SCIPisLE(scip, newlhs, newrhs));
10073  SCIP_CALL( chgLhs(scip, cons, newlhs) );
10074  SCIP_CALL( chgRhs(scip, cons, newrhs) );
10075  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10076 
10077  /* allocate temporary memory */
10078  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10079 
10080  /* set up the multi-aggregation */
10081  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10082  for( v = 0; v < consdata->nvars; ++v )
10083  {
10084  scalars[v] = -consdata->vals[v]/slackcoef;
10085  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10086  }
10087  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10088  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10089  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10090 
10091  /* perform the multi-aggregation */
10092  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10093  &infeasible, &aggregated) );
10094  assert(aggregated);
10095 
10096  /* free temporary memory */
10097  SCIPfreeBufferArray(scip, &scalars);
10098 
10099  /* check for infeasible aggregation */
10100  if( infeasible )
10101  {
10102  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10103  *cutoff = TRUE;
10104  return SCIP_OKAY;
10105  }
10106 
10107  (*naggrvars)++;
10108 
10109  /* delete the constraint if it became redundant */
10110  if( bestremovescons )
10111  {
10112  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10113  SCIP_CALL( SCIPdelCons(scip, cons) );
10114 
10115  if( !consdata->upgraded )
10116  (*ndelconss)++;
10117  }
10118  }
10119  else if( ncontvars == 1 )
10120  {
10121  SCIP_VAR* var;
10122 
10123  assert(0 <= contvarpos && contvarpos < consdata->nvars);
10124  var = vars[contvarpos];
10125  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
10126 
10127  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10128  {
10129  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10130  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10131  {
10132  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10133  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10134  SCIPconsGetName(cons), SCIPvarGetName(var));
10135  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10136  if( infeasible )
10137  {
10138  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10139  *cutoff = TRUE;
10140 
10141  return SCIP_OKAY;
10142  }
10143  }
10144  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10145  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10146  else if( !SCIPdoNotAggr(scip) )
10147  {
10148  SCIP_VAR* newvar;
10149  SCIP_Real absval;
10150  char newvarname[SCIP_MAXSTRLEN];
10151  SCIP_Bool redundant;
10152  SCIP_Bool aggregated;
10153 
10154  absval = REALABS(vals[contvarpos]);
10155 
10156  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10157 
10158  /* create new implicit variable for aggregation */
10159  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10161 
10162  /* add new variable to problem */
10163  SCIP_CALL( SCIPaddVar(scip, newvar) );
10164 
10165 #ifdef WITH_DEBUG_SOLUTION
10166  if( SCIPdebugIsMainscip(scip) )
10167  {
10168  SCIP_Real varval;
10169  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10170  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10171  }
10172 #endif
10173 
10174  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10175  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10176  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10177 
10178  /* aggregate continuous and implicit variable */
10179  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10180 
10181  if( infeasible )
10182  {
10183  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10184  SCIPvarGetName(var), SCIPvarGetName(newvar));
10185  *cutoff = TRUE;
10186 
10187  /* release implicit variable */
10188  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10189 
10190  return SCIP_OKAY;
10191  }
10192 
10193  /* release implicit variable */
10194  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10195 
10196  if( aggregated )
10197  (*naggrvars)++;
10198  else
10199  return SCIP_OKAY;
10200  }
10201 
10202  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10203  * again
10204  */
10205  consdata->boundstightened = 0;
10206  consdata->rangedrowpropagated = 0;
10207  consdata->presolved = FALSE;
10208  }
10209  }
10210  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10211  {
10212  SCIP_VAR* var;
10213 
10214  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10215  * -> we don't convert integers into implints if the row is a 0/1-row
10216  */
10217  assert(varsintegral);
10218  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10219  var = vars[intvarpos];
10220  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10221 
10222  if( coefsintegral
10223  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10224  && SCIPisFeasIntegral(scip, consdata->rhs) )
10225  {
10226  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10227  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10228  SCIPconsGetName(cons), SCIPvarGetName(var));
10229  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10230  if( infeasible )
10231  {
10232  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10233  *cutoff = TRUE;
10234 
10235  return SCIP_OKAY;
10236  }
10237  }
10238  }
10239 
10240  return SCIP_OKAY;
10241 }
10242 
10243 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10244 static
10246  SCIP* scip, /**< SCIP data structure */
10247  SCIP_CONSDATA* consdata, /**< linear constraint data */
10248  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10249  * objective function */
10250  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10251  * this constraint */
10252  )
10253 {
10254  SCIP_VAR** vars;
10255  SCIP_VAR* var;
10256  SCIP_Real objval;
10257  SCIP_Bool negated;
10258  int nvars;
10259  int v;
10260 
10261  vars = consdata->vars;
10262  nvars = consdata->nvars;
10263 
10264  assert(vars != NULL);
10265 
10266  for( v = 0; v < nvars; ++v )
10267  {
10268  negated = FALSE;
10269  var = vars[v];
10270  assert(var != NULL);
10271 
10272  if( SCIPvarIsNegated(var) )
10273  {
10274  negated = TRUE;
10275  var = SCIPvarGetNegatedVar(var);
10276  assert(var != NULL);
10277  }
10278 
10279  objval = SCIPvarGetObj(var);
10280 
10281  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10282  * function
10283  */
10284  if( SCIPisZero(scip, objval) )
10285  return FALSE;
10286  else
10287  {
10288  SCIP_Real val;
10289 
10290  val = consdata->vals[v];
10291 
10292  if( negated )
10293  {
10294  if( v == 0 )
10295  {
10296  /* the first variable defines the scale */
10297  (*scale) = val / -objval;
10298 
10299  (*offset) += val;
10300  }
10301  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10302  (*offset) += val;
10303  else
10304  return FALSE;
10305  }
10306  else if( v == 0 )
10307  {
10308  /* the first variable defines the scale */
10309  (*scale) = val / objval;
10310  }
10311  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10312  return FALSE;
10313  }
10314  }
10315 
10316  return TRUE;
10317 }
10318 
10319 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10320  * objective coefficients and add an objective offset
10321  */
10322 static
10324  SCIP* scip, /**< SCIP data structure */
10325  SCIP_CONS* cons, /**< linear equation constraint */
10326  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10327  )
10328 {
10329  SCIP_CONSDATA* consdata;
10330  SCIP_Real offset;
10331  SCIP_Real scale;
10332  SCIP_Bool applicable;
10333  int nobjvars;
10334  int nvars;
10335  int v;
10336 
10337  assert(scip != NULL);
10338  assert(cons != NULL);
10339  assert(conshdlrdata != NULL);
10340 
10341  consdata = SCIPconsGetData(cons);
10342  assert(consdata != NULL);
10343  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10344 
10345  nvars = consdata->nvars;
10346  nobjvars = SCIPgetNObjVars(scip);
10347 
10348  /* check if the linear equality constraints does not have more variables than the objective function */
10349  if( nvars > nobjvars || nvars == 0 )
10350  return SCIP_OKAY;
10351 
10352  /* check for allowance of algorithm */
10353  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10354  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10355  return SCIP_OKAY;
10356 
10357  offset = consdata->rhs;
10358  scale = 1.0;
10359 
10360  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10361  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10362 
10363  if( applicable )
10364  {
10365  SCIP_VAR** vars;
10366 
10367  vars = consdata->vars;
10368  assert(vars != NULL);
10369 
10370  offset /= scale;
10371 
10372  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10373  SCIPconsGetName(cons), consdata->rhs, offset);
10374 
10375  /* set all objective coefficient to zero */
10376  for( v = 0; v < nvars; ++v )
10377  {
10378  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10379  }
10380 
10381  /* add an objective offset */
10382  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10383  }
10384 
10385  return SCIP_OKAY;
10386 }
10387 
10388 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10389 static
10391  SCIP* scip, /**< SCIP data structure */
10392  SCIP_CONS* cons, /**< constraint */
10393  SCIP_Real primalbound /**< feasible primal bound */
10394  )
10395 {
10396  SCIP_Real cutoffbound;
10397 
10398  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10399  * accepted
10400  */
10401  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10402 
10403  if( cutoffbound < SCIPgetCutoffbound(scip) )
10404  {
10405  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10406 
10407  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10408  }
10409  else
10410  {
10411  SCIP_CONSDATA* consdata;
10412 
10413  consdata = SCIPconsGetData(cons);
10414  assert(consdata != NULL);
10415 
10416  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10417  * resulted from one side
10418  */
10419  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10420  {
10421  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10422  * propagation
10423  */
10424  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10425  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10426  }
10427  }
10428 
10429  return SCIP_OKAY;
10430 }
10431 
10432 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10433  * constraint enters the LP by setting the initial and separated flag to FALSE
10434  */
10435 static
10437  SCIP* scip, /**< SCIP data structure */
10438  SCIP_CONS* cons, /**< linear constraint */
10439  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10440  )
10441 {
10442  SCIP_CONSDATA* consdata;
10443  SCIP_Real offset;
10444  SCIP_Real scale;
10445  SCIP_Bool applicable;
10446  int nobjvars;
10447  int nvars;
10448 
10449  assert(scip != NULL);
10450  assert(cons != NULL);
10451  assert(conshdlrdata != NULL);
10452 
10453  consdata = SCIPconsGetData(cons);
10454  assert(consdata != NULL);
10456  /* ignore equalities since these are covered by the method checkPartialObjective() */
10457  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10458  return SCIP_OKAY;
10459 
10460  nvars = consdata->nvars;
10461  nobjvars = SCIPgetNObjVars(scip);
10462 
10463  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10464  * initial and/or separated flag is set to FALSE
10465  */
10466  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10467  return SCIP_OKAY;
10468 
10469  offset = 0.0;
10470  scale = 1.0;
10471 
10472  /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10473  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10474  */
10475  if( nobjvars == 0 )
10476  return SCIP_OKAY;
10477 
10478  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10479  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10480 
10481  if( applicable )
10482  {
10483  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10484  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10485 
10486  if( SCIPisPositive(scip, scale) )
10487  {
10488  if( conshdlrdata->detectcutoffbound && rhsfinite )
10489  {
10490  SCIP_Real primalbound;
10491 
10492  primalbound = (consdata->rhs - offset) / scale;
10493 
10494  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10495  SCIPconsGetName(cons), primalbound);
10496 
10497  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10498  }
10499 
10500  if( conshdlrdata->detectlowerbound && lhsfinite )
10501  {
10502  SCIP_Real lowerbound;
10503 
10504  lowerbound = (consdata->lhs - offset) / scale;
10505 
10506  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10507  SCIPconsGetName(cons), lowerbound);
10508 
10509  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10510  }
10511 
10512  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10513  (conshdlrdata->detectlowerbound && !rhsfinite) )
10514  {
10515  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10516  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10517  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10518  }
10519  }
10520  else
10521  {
10522  if( conshdlrdata->detectlowerbound && rhsfinite )
10523  {
10524  SCIP_Real lowerbound;
10525 
10526  lowerbound = (consdata->rhs - offset) / scale;
10527 
10528  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10529  SCIPconsGetName(cons), lowerbound);
10530 
10531  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10532  }
10533 
10534  if( conshdlrdata->detectcutoffbound && lhsfinite )
10535  {
10536  SCIP_Real primalbound;
10537 
10538  primalbound = (consdata->lhs - offset) / scale;
10539 
10540  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10541  SCIPconsGetName(cons), primalbound);
10542 
10543  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10544  }
10545 
10546  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10547  (conshdlrdata->detectlowerbound && !lhsfinite) )
10548  {
10549  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10550  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10551  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10552  }
10553  }
10554  }
10555 
10556  return SCIP_OKAY;
10557 }
10558 
10559 /** converts special equalities */
10560 static
10562  SCIP* scip, /**< SCIP data structure */
10563  SCIP_CONS* cons, /**< linear constraint */
10564  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10565  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10566  int* nfixedvars, /**< pointer to count number of fixed variables */
10567  int* naggrvars, /**< pointer to count number of aggregated variables */
10568  int* ndelconss /**< pointer to count number of deleted constraints */
10569  )
10570 {
10571  SCIP_CONSDATA* consdata;
10572 
10573  assert(scip != NULL);
10574  assert(cons != NULL);
10575  assert(conshdlrdata != NULL);
10576  assert(cutoff != NULL);
10577  assert(nfixedvars != NULL);
10578  assert(naggrvars != NULL);
10579  assert(ndelconss != NULL);
10581  consdata = SCIPconsGetData(cons);
10582  assert(consdata != NULL);
10583  assert(consdata->removedfixings);
10584 
10585  /* do nothing on inequalities */
10586  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10587  return SCIP_OKAY;
10588 
10589  /* depending on the number of variables, call a special conversion method */
10590  if( consdata->nvars == 1 )
10591  {
10592  /* fix variable */
10593  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10594  }
10595  else if( consdata->nvars == 2 )
10596  {
10597  /* aggregate one of the variables */
10598  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10599  }
10600  else
10601  {
10602  /* check if the equality is part of the objective function */
10603  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10604 
10605  /* try to multi-aggregate one of the variables */
10606  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10607  }
10608 
10609  return SCIP_OKAY;
10610 }
10611 
10612 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10613  * integral
10614  */
10615 static
10617  SCIP* scip, /**< SCIP data structure */
10618  SCIP_CONSDATA* consdata, /**< linear constraint */
10619  int pos, /**< position of variable to be left out */
10620  SCIP_Real val /**< value to divide the coefficients by */
10621  )
10622 {
10623  int v;
10624 
10625  assert(scip != NULL);
10626  assert(consdata != NULL);
10627  assert(0 <= pos && pos < consdata->nvars);
10628 
10629  for( v = 0; v < consdata->nvars; ++v )
10630  {
10631  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10632  return FALSE;
10633  }
10634 
10635  return TRUE;
10636 }
10637 
10638 /** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$,
10639  * check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$
10640  */
10641 static
10643  SCIP* scip, /**< SCIP data structure */
10644  SCIP_Real side, /**< lhs or rhs */
10645  SCIP_Real val, /**< coefficient */
10646  SCIP_Real minresactivity, /**< minimal residual activity */
10647  SCIP_Real maxresactivity, /**< maximal residual activity */
10648  SCIP_Real* minval, /**< pointer to store calculated minval */
10649  SCIP_Real* maxval /**< pointer to store calculated maxval */
10650  )
10651 {
10652  assert(scip != NULL);
10653  assert(minval != NULL);
10654  assert(maxval != NULL);
10655 
10656  if( val > 0.0 )
10657  {
10658  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10659  *minval = -maxresactivity;
10660  else
10661  *minval = (side - maxresactivity)/val;
10662 
10663  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10664  *maxval = -minresactivity;
10665  else
10666  *maxval = (side - minresactivity)/val;
10667  }
10668  else
10669  {
10670  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10671  *minval = minresactivity;
10672  else
10673  *minval = (side - minresactivity)/val;
10674 
10675  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10676  *maxval = maxresactivity;
10677  else
10678  *maxval = (side - maxresactivity)/val;
10679  }
10680 }
10681 
10682 
10683 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10684  * linear inequality
10685  */
10686 static
10688  SCIP* scip, /**< SCIP data structure */
10689  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10690  SCIP_CONS* cons, /**< linear constraint */
10691  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10692  int* nfixedvars, /**< pointer to count number of fixed variables */
10693  int* naggrvars, /**< pointer to count number of aggregated variables */
10694  int* ndelconss /**< pointer to count number of deleted constraints */
10695  )
10696 {
10697  SCIP_CONSDATA* consdata;
10698  SCIP_Bool lhsexists;
10699  SCIP_Bool rhsexists;
10700  SCIP_Bool bestisint;
10701  SCIP_Bool bestislhs;
10702  SCIP_Real minabsval;
10703  SCIP_Real maxabsval;
10704  int bestpos;
10705  int i;
10706  int maxotherlocks;
10707 
10708  assert(scip != NULL);
10709  assert(cons != NULL);
10710  assert(cutoff != NULL);
10711  assert(nfixedvars != NULL);
10712  assert(naggrvars != NULL);
10713  assert(ndelconss != NULL);
10714 
10715  /* only process checked constraints (for which the locks are increased);
10716  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10717  * dualfix presolver
10718  */
10719  if( !SCIPconsIsChecked(cons) )
10720  return SCIP_OKAY;
10721 
10722  consdata = SCIPconsGetData(cons);
10723  assert(consdata != NULL);
10724 
10725  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10726  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10727 
10728  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10729  * can use it safely for aggregation and break the search loop
10730  */
10731  bestpos = -1;
10732  bestisint = TRUE;
10733  bestislhs = FALSE;
10734 
10735  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10736  * everything else would produce fill-in. Exceptions:
10737  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10738  * produced.
10739  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10740  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10741  * six nonzeros (two variables per substitution).
10742  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10743  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10744  * six nonzeros (three variables per substitution). God exists!
10745  */
10746  if( consdata->nvars <= 2 )
10747  maxotherlocks = INT_MAX;
10748  else if( consdata->nvars == 3 )
10749  maxotherlocks = 3;
10750  else if( consdata->nvars == 4 )
10751  maxotherlocks = 2;
10752  else
10753  maxotherlocks = 1;
10754 
10755  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10756  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10757  maxotherlocks++;
10758 
10759  minabsval = SCIPinfinity(scip);
10760  maxabsval = -1.0;
10761  for( i = 0; i < consdata->nvars && bestisint; ++i )
10762  {
10763  SCIP_VAR* var;
10764  SCIP_Bool isint;
10765  SCIP_Real val;
10766  SCIP_Real absval;
10767  SCIP_Real obj;
10768  SCIP_Real lb;
10769  SCIP_Real ub;
10770  SCIP_Bool agglhs;
10771  SCIP_Bool aggrhs;
10772 
10773  val = consdata->vals[i];
10774  absval = REALABS(val);
10775 
10776  /* calculate minimal and maximal absolute value */
10777  if( absval < minabsval )
10778  minabsval = absval;
10779  if( absval > maxabsval )
10780  maxabsval = absval;
10781 
10782  /* do not try to multi aggregate, when numerical bad */
10783  if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10784  return SCIP_OKAY;
10785 
10786  var = consdata->vars[i];
10788 
10789  /* if we already found a candidate, skip integers */
10790  if( bestpos >= 0 && isint )
10791  continue;
10792 
10793  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10794  * active, fixed, or single-aggregated with another binary variable
10795  */
10796  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10797  continue;
10798 
10799  if ( SCIPdoNotMultaggrVar(scip, var) )
10800  continue;
10801 
10802  val = consdata->vals[i];
10803  obj = SCIPvarGetObj(var);
10804  lb = SCIPvarGetLbGlobal(var);
10805  ub = SCIPvarGetUbGlobal(var);
10806 
10807  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10808  *
10809  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10810  * - constraint is the only one that forbids fixing the variable to its lower bound
10811  * - 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
10812  *
10813  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10814  * - constraint is the only one that forbids fixing the variable to its upper bound
10815  * - 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
10816  *
10817  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10818  * - constraint is the only one that forbids fixing the variable to its upper bound
10819  * - 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
10820  *
10821  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10822  * - constraint is the only one that forbids fixing the variable to its lower bound
10823  * - 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
10824  *
10825  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10826  * of all x_j
10827  * furthermore: we only want to apply this, if no fill-in will be produced
10828  */
10829  agglhs = lhsexists
10830  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10831  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10832  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10833  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10834  aggrhs = rhsexists
10835  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10836  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10837  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10838  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10839  if( agglhs || aggrhs )
10840  {
10841  SCIP_Real minresactivity;
10842  SCIP_Real maxresactivity;
10843  SCIP_Real minval;
10844  SCIP_Real maxval;
10845  SCIP_Bool minisrelax;
10846  SCIP_Bool maxisrelax;
10847  SCIP_Bool isminsettoinfinity;
10848  SCIP_Bool ismaxsettoinfinity;
10849 
10850  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10851  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10852  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10853  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10854 
10855  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10856  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10857  * This is needed, because we do not want to rely on relaxed finite resactivities.
10858  */
10859  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10860 
10861  if( agglhs )
10862  {
10863  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10864  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10865 
10866  assert(SCIPisLE(scip, minval, maxval));
10867  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10868  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10869  {
10870  SCIP_Real oldmaxresactivity;
10871  SCIP_Real oldminresactivity;
10872  SCIP_Bool recalculated;
10873 
10874  recalculated = FALSE;
10875  oldmaxresactivity = maxresactivity;
10876  oldminresactivity = minresactivity;
10877 
10878  /* check minresactivity for reliability */
10879  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10880  {
10881  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10882  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10883  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10884  }
10885 
10886  /* check maxresactivity for reliability */
10887  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10888  {
10889  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10890  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10891  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10892  }
10893 
10894  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10895  if( recalculated )
10896  {
10897  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10898 
10899  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10900  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10901 
10902  assert(SCIPisLE(scip, minval, maxval));
10903  }
10904 
10905  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10906  {
10907  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10908  * in the multi-aggregation
10909  */
10910  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10911  {
10912  bestpos = i;
10913  bestisint = isint;
10914  bestislhs = TRUE;
10915  continue; /* no need to also look at the right hand side */
10916  }
10917  }
10918  }
10919  }
10920 
10921  if( aggrhs )
10922  {
10923  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10924  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10925 
10926  assert(SCIPisLE(scip,minval,maxval));
10927  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10928  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10929  {
10930  SCIP_Real oldmaxresactivity;
10931  SCIP_Real oldminresactivity;
10932  SCIP_Bool recalculated;
10933 
10934  recalculated = FALSE;
10935  oldmaxresactivity = maxresactivity;
10936  oldminresactivity = minresactivity;
10937 
10938  /* check minresactivity for reliability */
10939  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10940  {
10941  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10942  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10943  }
10944 
10945  /* check maxresactivity for reliability */
10946  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10947  {
10948  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10949  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10950  }
10951 
10952  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10953  if( recalculated )
10954  {
10955  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10956  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10957  assert(SCIPisLE(scip,minval,maxval));
10958  }
10959 
10960  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10961  {
10962  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10963  * in the multi-aggregation
10964  */
10965  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10966  {
10967  bestpos = i;
10968  bestisint = isint;
10969  bestislhs = FALSE;
10970  }
10971  }
10972  }
10973  }
10974  }
10975  }
10976 
10977  if( bestpos >= 0 )
10978  {
10979  SCIP_VAR** aggrvars;
10980  SCIP_Real* aggrcoefs;
10981  SCIP_Real aggrconst;
10982  SCIP_VAR* bestvar;
10983  SCIP_Real bestval;
10984  SCIP_Real epsilon;
10985  int naggrs;
10986  int j;
10987  SCIP_Bool infeasible;
10988  SCIP_Bool aggregated;
10989  SCIP_Bool samevar;
10990  int supinf; /* counter for infinite contributions to the supremum of a possible
10991  * multi-aggregation
10992  */
10993  int infinf; /* counter for infinite contributions to the infimum of a possible
10994  * multi-aggregation
10995  */
10996 
10997  assert(!bestislhs || lhsexists);
10998  assert(bestislhs || rhsexists);
10999 
11000  bestvar = consdata->vars[bestpos];
11001  bestval = consdata->vals[bestpos];
11002  assert(bestisint ==
11004 
11005  /* allocate temporary memory */
11006  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11007  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11008 
11009  /* set up the multi-aggregation */
11010  SCIPdebugPrintCons(scip, cons, NULL);
11011  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11012  naggrs = 0;
11013  supinf = 0;
11014  infinf = 0;
11015  samevar = FALSE;
11016  epsilon = SCIPepsilon(scip);
11017 
11018  for( j = 0; j < consdata->nvars; ++j )
11019  {
11020  if( j != bestpos )
11021  {
11022  SCIP_Real absaggrcoef;
11023 
11024  aggrvars[naggrs] = consdata->vars[j];
11025  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11026  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
11027 
11028  absaggrcoef = REALABS(aggrcoefs[naggrs]);
11029 
11030  /* do not try to multi aggregate, when numerical bad */
11031  if( absaggrcoef < epsilon )
11032  {
11033  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11034 
11035  /* free temporary memory */
11036  SCIPfreeBufferArray(scip, &aggrcoefs);
11037  SCIPfreeBufferArray(scip, &aggrvars);
11038 
11039  return SCIP_OKAY;
11040  }
11041 
11042  if( bestisint )
11043  {
11044  /* coefficient must be integral: round it to exact integral value */
11045  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
11046  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
11047  }
11048 
11049  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
11050  {
11051  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11052  {
11053  ++supinf;
11054  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11055  {
11056  ++infinf;
11057  samevar = TRUE;
11058  }
11059  }
11060  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11061  ++infinf;
11062  }
11063  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11064  {
11065  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11066  {
11067  ++supinf;
11068  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11069  {
11070  ++infinf;
11071  samevar = TRUE;
11072  }
11073  }
11074  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11075  ++infinf;
11076  }
11077 
11078  naggrs++;
11079  }
11080  }
11081  assert(!samevar || (supinf > 0 && infinf > 0));
11082 
11083  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11084  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11085  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11086  assert(naggrs == consdata->nvars-1);
11087 
11088  /* right hand side must be integral: round it to exact integral value */
11089  if( bestisint )
11090  {
11091  assert(SCIPisIntegral(scip, aggrconst));
11092  aggrconst = SCIPfloor(scip, aggrconst+0.5);
11093  }
11094 
11095  aggregated = FALSE;
11096  infeasible = FALSE;
11097 
11098  /* perform the multi-aggregation */
11099  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11100  {
11101  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11102  * also convertLongEquality() early termination due to coefficients
11103  */
11104  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11105 
11106  /** if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11107  * the implicitness might rely on the constraint and the integrality of bestvar
11108  */
11109  if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11110  {
11111  SCIP_Bool infeasiblevartypechg;
11112 
11113  for( j = 0; j < naggrs; ++j)
11114  {
11115  /** If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11116  * lead to infeasibility
11117  */
11118  if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11119  {
11120  SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11121  assert(!infeasiblevartypechg);
11122  }
11123  }
11124  }
11125  }
11126  else
11127  {
11128  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11129  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11130  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11131  }
11132  /* free temporary memory */
11133  SCIPfreeBufferArray(scip, &aggrcoefs);
11134  SCIPfreeBufferArray(scip, &aggrvars);
11135 
11136  /* check for infeasible aggregation */
11137  if( infeasible )
11138  {
11139  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11140  *cutoff = TRUE;
11141  return SCIP_OKAY;
11142  }
11143 
11144  /* delete the constraint, if the aggregation was successful */
11145  if( aggregated )
11146  {
11147  SCIP_CALL( SCIPdelCons(scip, cons) );
11148 
11149  if( !consdata->upgraded )
11150  (*ndelconss)++;
11151  (*naggrvars)++;
11152  }
11153  else
11154  {
11155  SCIPdebugMsg(scip, "aggregation non successful!\n");
11156  }
11157  }
11158 
11159  return SCIP_OKAY;
11160 }
11161 
11162 #define BINWEIGHT 1
11163 #define INTWEIGHT 4
11164 #define CONTWEIGHT 8
11165 
11166 /** gets weight for variable in a "weighted number of variables" sum */
11167 static
11168 int getVarWeight(
11169  SCIP_VAR* var /**< variable to get weight for */
11170  )
11171 {
11172  switch( SCIPvarGetType(var) )
11173  {
11174  case SCIP_VARTYPE_BINARY:
11175  return BINWEIGHT;
11176  case SCIP_VARTYPE_INTEGER:
11177  case SCIP_VARTYPE_IMPLINT:
11178  return INTWEIGHT;
11180  return CONTWEIGHT;
11181  default:
11182  SCIPerrorMessage("invalid variable type\n");
11184  return 0; /*lint !e527*/
11185  }
11186 }
11188 /** tries to aggregate variables in equations a^Tx = lhs
11189  * in case there are at most two binary variables with an odd coefficient and all other
11190  * variables are not continuous and have an even coefficient then:
11191  * - exactly one odd binary variables
11192  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11193  * - lhs is odd -> y = 1
11194  * - lhs is even -> y = 0
11195  * - exactly two odd binary variables
11196  * aggregate the two binary variables with odd coefficient
11197  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11198  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11199  */
11200 static
11202  SCIP* scip, /**< SCIP data structure */
11203  SCIP_CONS* cons, /**< linear constraint */
11204  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11205  int* nfixedvars, /**< pointer to count number of fixed variables */
11206  int* naggrvars /**< pointer to count number of aggregated variables */
11207  )
11208 { /*lint --e{715}*/
11209  SCIP_CONSDATA* consdata;
11210  SCIP_Bool success;
11211 
11212  assert( scip != NULL );
11213  assert( cons != NULL );
11214 
11215  consdata = SCIPconsGetData(cons);
11216  assert( consdata != NULL );
11217 
11218  /* check if the linear constraint is an equation with integral right hand side */
11219  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11220  return SCIP_OKAY;
11221 
11222  /* try to fix and aggregated variables until nothing is possible anymore */
11223  do
11224  {
11225  int v;
11226  int nvars;
11227  SCIP_VAR** vars;
11228  SCIP_Real* vals;
11229  SCIP_Real lhs;
11230  SCIP_Bool lhsodd;
11231 
11232  SCIP_Bool infeasible;
11233  SCIP_Bool fixed;
11234  SCIP_Bool aggregated;
11235  SCIP_Bool redundant;
11236 
11237  SCIP_VAR* var1;
11238  SCIP_VAR* var2;
11239  int noddvars;
11240 
11241  success = FALSE;
11242 
11243  lhs = consdata->lhs;
11244  vars = consdata->vars;
11245  vals = consdata->vals;
11246  nvars = consdata->nvars;
11247 
11248  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11249 
11250  var1 = NULL;
11251  var2 = NULL;
11252  noddvars = 0;
11253 
11254  /* search for binary variables with an odd coefficient */
11255  for( v = 0; v < nvars && noddvars < 3; ++v )
11256  {
11257  SCIP_Longint val;
11258 
11259  /* all coefficients and variables have to be integral */
11260  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11261  return SCIP_OKAY;
11262 
11263  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11264  if( val % 2 != 0 )
11265  {
11266  /* the odd values have to belong to binary variables */
11267  if( !SCIPvarIsBinary(vars[v]) )
11268  return SCIP_OKAY;
11269 
11270  if( noddvars == 0 )
11271  var1 = vars[v];
11272  else
11273  var2 = vars[v];
11274 
11275  noddvars++;
11276  }
11277  }
11278 
11279  /* check lhs is odd or even */
11280  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11281 
11282  if( noddvars == 1 )
11283  {
11284  assert( var1 != NULL );
11285 
11286  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11287  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11288 
11289  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11290 
11291  /* check for infeasibility of fixing */
11292  if( infeasible )
11293  {
11294  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11295  *cutoff = TRUE;
11296  return SCIP_OKAY;
11297  }
11298 
11299  if( fixed )
11300  {
11301  SCIPdebugMsg(scip, " -> feasible fixing\n");
11302  (*nfixedvars)++;
11303  success = TRUE;
11304  }
11305  }
11306  else if( noddvars == 2 )
11307  {
11308  assert( var1 != NULL );
11309  assert( var2 != NULL );
11310 
11311  /* aggregate the two variables with odd coefficient
11312  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11313  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11314  */
11315  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11316  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11317 
11318  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11319  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11320 
11321  /* check for infeasibility of aggregation */
11322  if( infeasible )
11323  {
11324  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11325  *cutoff = TRUE;
11326  return SCIP_OKAY;
11327  }
11328 
11329  /* count the aggregation */
11330  if( aggregated )
11331  {
11332  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11333  (*naggrvars)++;
11334  success = TRUE;
11335  }
11336  }
11337 
11338  if( success )
11339  {
11340  /* apply fixings and aggregation to successfully rerun this presolving step */
11341  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11342 
11343  if( infeasible )
11344  {
11345  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11346  *cutoff = TRUE;
11347  return SCIP_OKAY;
11348  }
11349 
11350  /* normalize constraint */
11351  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11352 
11353  if( infeasible )
11354  {
11355  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11356  *cutoff = TRUE;
11357  return SCIP_OKAY;
11358  }
11359  }
11360  }
11361  while( success );
11362 
11363  return SCIP_OKAY;
11364 }
11365 
11366 
11367 
11368 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11369  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11370  * coefficients
11371  */
11372 static
11373 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11374 { /*lint --e{715}*/
11375  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11376  SCIP_VARTYPE vartype1;
11377  SCIP_VARTYPE vartype2;
11378  SCIP_Real value;
11379 
11380  assert(consdata != NULL);
11381  assert(0 <= ind1 && ind1 < consdata->nvars);
11382  assert(0 <= ind2 && ind2 < consdata->nvars);
11383 
11384  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11385  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11386 
11387  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11388  {
11389  /* continuous varibles will be sorted to the back */
11390  if( vartype2 != vartype1 )
11391  return +1;
11392  /* both variables are continuous */
11393  else
11394  return 0;
11395  }
11396  /* continuous variables will be sorted to the back */
11397  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11398  return -1;
11399 
11400  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11401 
11402  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11403  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11404 }
11405 
11406 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11407  * common divisor
11408  *
11409  * 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
11410  * constraint to 1^Tx = 1
11411  */
11412 static
11414  SCIP* scip, /**< SCIP data structure */
11415  SCIP_CONS* cons, /**< linear constraint */
11416  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11417  int* nchgsides /**< pointer to store the amount of changed sides */
11418  )
11419 {
11420  SCIP_CONSDATA* consdata;
11421  SCIP_VAR** vars;
11422  SCIP_Real* vals;
11423  SCIP_Real minval;
11424  SCIP_Real secondminval;
11425  SCIP_Real maxval;
11426  SCIP_Real lhs;
11427  SCIP_Real rhs;
11428  int nvars;
11429  int v;
11430 
11431  /* we must not change a modifiable constraint in any way */
11433  return SCIP_OKAY;
11434 
11435  if( SCIPconsIsDeleted(cons) )
11436  return SCIP_OKAY;
11437 
11438  consdata = SCIPconsGetData(cons);
11439  assert(consdata != NULL);
11440 
11441  nvars = consdata->nvars;
11442 
11443  /* do not check empty or bound-constraints */
11444  if( nvars < 2 )
11445  return SCIP_OKAY;
11446 
11447  vals = consdata->vals;
11448  vars = consdata->vars;
11449  assert(vars != NULL);
11450  assert(vals != NULL);
11451 
11452  lhs = consdata->lhs;
11453  rhs = consdata->rhs;
11454  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11455  assert(!SCIPisNegative(scip, rhs));
11456 
11457  minval = SCIP_INVALID;
11458  secondminval = SCIP_INVALID;
11459  maxval = -SCIP_INVALID;
11460 
11461  for( v = nvars - 1; v >= 0; --v )
11462  {
11463  if( SCIPvarIsBinary(vars[v]) )
11464  {
11465  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11466  {
11467  secondminval = minval;
11468  minval = vals[v];
11469  }
11470  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11471  secondminval = vals[v];
11472 
11473  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11474  maxval = vals[v];
11475  }
11476  else
11477  break;
11478  }
11479 
11480  /* check if all variables are binary */
11481  if( v == -1 )
11482  {
11483  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11484  return SCIP_OKAY;
11485 
11486  /* check if we can and need to choose exactly one binary variable */
11487  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11488  {
11489  /* change all coefficients to 1.0 */
11490  for( v = nvars - 1; v >= 0; --v )
11491  {
11492  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11493  }
11494  (*nchgcoefs) += nvars;
11495 
11496  /* replace old right and left hand side with 1.0 */
11497  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11498  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11499  (*nchgsides) += 2;
11500  }
11501  }
11502 
11503  return SCIP_OKAY;
11504 }
11505 
11506 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11507  * for equations @see rangedRowSimplify() will be called
11508  *
11509  * there are several different coefficient reduction steps which will be applied
11510  *
11511  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11512  *
11513  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11514  *
11515  * 2. We try to remove redundant fractional parts in a constraint
11516  *
11517  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11518  *
11519  * 3. We are using the greatest common divisor for further reductions
11520  *
11521  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11522  * integral
11523  */
11524 static
11526  SCIP* scip, /**< SCIP data structure */
11527  SCIP_CONS* cons, /**< linear constraint */
11528  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11529  int* nchgsides, /**< pointer to store the amount of changed sides */
11530  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11531  )
11532 {
11533  SCIP_CONSDATA* consdata;
11534  SCIP_VAR** vars;
11535  SCIP_Real* vals;
11536  int* perm;
11537  SCIP_Real minactsub;
11538  SCIP_Real maxactsub;
11539  SCIP_Real siderest;
11540  SCIP_Real feastol;
11541  SCIP_Real newcoef;
11542  SCIP_Real absval;
11543  SCIP_Real minact;
11544  SCIP_Real maxact;
11545  SCIP_Real side;
11546  SCIP_Real lhs;
11547  SCIP_Real rhs;
11548  SCIP_Real lb;
11549  SCIP_Real ub;
11550  SCIP_Longint restcoef;
11551  SCIP_Longint oldgcd;
11552  SCIP_Longint rest;
11553  SCIP_Longint gcd;
11554  SCIP_Bool isminsettoinfinity;
11555  SCIP_Bool ismaxsettoinfinity;
11556  SCIP_Bool isminrelax;
11557  SCIP_Bool ismaxrelax;
11558  SCIP_Bool allcoefintegral;
11559  SCIP_Bool onlybin;
11560  SCIP_Bool hasrhs;
11561  SCIP_Bool haslhs;
11562  int oldnchgcoefs;
11563  int oldnchgsides;
11564  int foundbin;
11565  int candpos;
11566  int candpos2;
11567  int offsetv;
11568  int nvars;
11569  int v;
11570  int w;
11571 
11572  assert(scip != NULL);
11573  assert(cons != NULL);
11574  assert(nchgcoefs != NULL);
11575  assert(nchgsides != NULL);
11576 
11577  *infeasible = FALSE;
11578 
11579  /* we must not change a modifiable constraint in any way */
11580  if( SCIPconsIsModifiable(cons) )
11581  return SCIP_OKAY;
11582 
11583  if( SCIPconsIsDeleted(cons) )
11584  return SCIP_OKAY;
11585 
11586  consdata = SCIPconsGetData(cons);
11587  assert(consdata != NULL);
11588 
11589  nvars = consdata->nvars;
11590 
11591  /* do not check empty or bound-constraints */
11592  if( nvars <= 2 )
11593  return SCIP_OKAY;
11594 
11595  /* update maximal activity delta if necessary */
11596  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11597  consdataRecomputeMaxActivityDelta(scip, consdata);
11598 
11599  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11600  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11601  checkMaxActivityDelta(scip, consdata);
11602 
11603  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11604  * accordingly
11605  */
11606  /* can only work with valid non-infinity activities per variable */
11607  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11608  return SCIP_OKAY;
11609 
11610  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11611  * but the eventsystem seems to be full
11612  */
11613  consdata->normalized = FALSE;
11614 
11615  /* normalize constraint */
11616  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11617  assert(nvars == consdata->nvars);
11618 
11619  if( *infeasible )
11620  return SCIP_OKAY;
11621 
11622  if( !consdata->normalized )
11623  return SCIP_OKAY;
11624 
11625  lhs = consdata->lhs;
11626  rhs = consdata->rhs;
11627  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11628  assert(!SCIPisNegative(scip, rhs));
11629 
11630  if( !SCIPisInfinity(scip, -lhs) )
11631  haslhs = TRUE;
11632  else
11633  haslhs = FALSE;
11634 
11635  if( !SCIPisInfinity(scip, rhs) )
11636  hasrhs = TRUE;
11637  else
11638  hasrhs = FALSE;
11639 
11640  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11641  SCIPdebug( oldnchgsides = *nchgsides; )
11642 
11643  /* @todo also work on ranged rows */
11644  if( haslhs && hasrhs )
11645  {
11646  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11647 
11648  return SCIP_OKAY;
11649  }
11650  assert(haslhs != hasrhs);
11651 
11652  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11653  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11654  assert(!haslhs || !SCIPisNegative(scip, lhs));
11655 
11656  /* get temporary memory to store the sorted permutation */
11657  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11658 
11659  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11660  * value of their coefficients
11661  */
11662  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11663 
11664  /* perform sorting after permutation array */
11665  permSortConsdata(consdata, perm, nvars);
11666  consdata->indexsorted = FALSE;
11667  consdata->coefsorted = FALSE;
11668 
11669  vars = consdata->vars;
11670  vals = consdata->vals;
11671  assert(vars != NULL);
11672  assert(vals != NULL);
11673  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11674 
11675  /* free temporary memory */
11676  SCIPfreeBufferArray(scip, &perm);
11677 
11678  /* only check constraints with at least two non continuous variables */
11679  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11680  return SCIP_OKAY;
11681 
11682  /* do not process constraints when all coefficients are 1.0 */
11683  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11684  return SCIP_OKAY;
11685 
11686  feastol = SCIPfeastol(scip);
11687 
11688  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11689  SCIPdebugPrintCons(scip, cons, NULL);
11690 
11691  /* get global activities */
11692  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11693  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11694 
11695  /* cannot work with infinite activities */
11696  if( isminsettoinfinity || ismaxsettoinfinity )
11697  return SCIP_OKAY;
11698 
11699  assert(!isminrelax);
11700  assert(!ismaxrelax);
11701  assert(maxact > minact);
11702  assert(!SCIPisInfinity(scip, -minact));
11703  assert(!SCIPisInfinity(scip, maxact));
11704 
11705  v = 0;
11706  offsetv = -1;
11707  side = haslhs ? lhs : rhs;
11708  minactsub = minact;
11709  maxactsub = maxact;
11710 
11711  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11712  * do not need to look at the large coefficients
11713  *
11714  * e.g. all x are binary, z are positive integer
11715  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11716  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11717  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11718  *
11719  * can be changed to
11720  *
11721  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11722  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11723  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11724  */
11725 
11726  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11727  * hand side, we cannot apply the extra reduction step and need to reset v
11728  *
11729  * 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
11730  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11731  * for all i is a solution
11732  *
11733  * also redundancy of variables would not be correctly determined in such a case
11734  */
11735  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11736  {
11737  v = 1;
11738 
11739  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11740  {
11741  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11742  * extra step, which might have worked
11743  */
11744  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11745  {
11746  v = 0;
11747  break;
11748  }
11749 
11750  ++v;
11751  }
11752 
11753  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11754  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11755  if( v == nvars )
11756  return SCIP_OKAY;
11757 
11758  /* cannot work with continuous variables which have a big coefficient */
11759  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11760  return SCIP_OKAY;
11761 
11762  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11763  if( SCIPisEQ(scip, side, -vals[v]) )
11764  v = 0;
11765 
11766  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11767  * reduction
11768  */
11769  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11770  v = 0;
11771 
11772  if( v > 0 )
11773  {
11774  assert(v < nvars);
11775 
11776  offsetv = v - 1;
11777 
11778  for( w = 0; w < v; ++w )
11779  {
11780  lb = SCIPvarGetLbGlobal(vars[w]);
11781  ub = SCIPvarGetUbGlobal(vars[w]);
11782 
11783  assert(vals[w] > 0);
11784 
11785  /* update residual activities */
11786  maxactsub -= ub * vals[w];
11787  minactsub -= lb * vals[w];
11788  assert(maxactsub > minactsub);
11789  }
11790  }
11791  }
11792 
11793  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11794  *
11795  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11796  *
11797  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11798  * to
11799  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11800  */
11801  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11802  {
11803  SCIP_Bool redundant = FALSE;
11804  SCIP_Bool numericsok;
11805  SCIP_Bool rredundant;
11806  SCIP_Bool lredundant;
11807 
11808 
11809  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11810  assert(gcd >= 1);
11811 
11812  if( v == 0 )
11813  {
11814  lb = SCIPvarGetLbGlobal(vars[0]);
11815  ub = SCIPvarGetUbGlobal(vars[0]);
11816 
11817  /* update residual activities */
11818  if( vals[0] > 0 )
11819  {
11820  maxactsub -= ub * vals[0];
11821  minactsub -= lb * vals[0];
11822  }
11823  else
11824  {
11825  maxactsub -= lb * vals[0];
11826  minactsub -= ub * vals[0];
11827  }
11828  assert(maxactsub > minactsub);
11829  ++v;
11830  }
11831 
11832  siderest = -SCIP_INVALID;
11833  allcoefintegral = TRUE;
11834 
11835  /* check if some variables always fit into the given constraint */
11836  for( ; v < nvars - 1; ++v )
11837  {
11838  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11839  break;
11840 
11841  if( !SCIPisIntegral(scip, vals[v]) )
11842  {
11843  allcoefintegral = FALSE;
11844  break;
11845  }
11846 
11847  /* calculate greatest common divisor for all general and binary variables */
11848  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11849 
11850  if( gcd == 1 )
11851  break;
11852 
11853  lb = SCIPvarGetLbGlobal(vars[v]);
11854  ub = SCIPvarGetUbGlobal(vars[v]);
11855 
11856  assert(!SCIPisInfinity(scip, -lb));
11857  assert(!SCIPisInfinity(scip, ub));
11858 
11859  /* update residual activities */
11860  if( vals[v] > 0 )
11861  {
11862  maxactsub -= ub * vals[v];
11863  minactsub -= lb * vals[v];
11864  }
11865  else
11866  {
11867  maxactsub -= lb * vals[v];
11868  minactsub -= ub * vals[v];
11869  }
11870  assert(SCIPisGE(scip, maxactsub, minactsub));
11871 
11872  if( hasrhs )
11873  {
11874  /* determine the remainder of the right hand side and the gcd */
11875  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11876  }
11877  else
11878  {
11879  /* determine the remainder of the left hand side and the gcd */
11880  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11881  if( SCIPisZero(scip, siderest) )
11882  siderest = gcd;
11883  }
11884 
11885  rredundant = hasrhs && maxactsub <= siderest && SCIPisGT(scip, minactsub, siderest - gcd);
11886  lredundant = haslhs && SCIPisLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11887 
11888  /* early termination if the activities deceed the gcd */
11889  if( offsetv == -1 && (rredundant || lredundant) )
11890  {
11891  redundant = TRUE;
11892  break;
11893  }
11894  }
11895  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11896 
11897  if( !redundant )
11898  {
11899  if( hasrhs )
11900  {
11901  /* determine the remainder of the right hand side and the gcd */
11902  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11903  }
11904  else
11905  {
11906  /* determine the remainder of the left hand side and the gcd */
11907  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11908  if( SCIPisZero(scip, siderest) )
11909  siderest = gcd;
11910  }
11911  }
11912  else
11913  ++v;
11914 
11915  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",
11916  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11917 
11918  /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11919  * reasonable absolute values */
11920  numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11921  REALABS(minactsub) < MAXACTVAL;
11922 
11923  rredundant = hasrhs && maxactsub <= siderest && SCIPisGT(scip, minactsub, siderest - gcd);
11924  lredundant = haslhs && SCIPisLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11925 
11926  /* check if we can remove redundant variables */
11927  if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11928  {
11929  SCIP_Real oldcoef;
11930 
11931  /* double check the redundancy */
11932 #ifndef NDEBUG
11933  SCIP_Real tmpminactsub = 0.0;
11934  SCIP_Real tmpmaxactsub = 0.0;
11935 
11936  /* recompute residual activities */
11937  for( w = v; w < nvars; ++w )
11938  {
11939  lb = SCIPvarGetLbGlobal(vars[w]);
11940  ub = SCIPvarGetUbGlobal(vars[w]);
11941 
11942  assert(!SCIPisInfinity(scip, -lb));
11943  assert(!SCIPisInfinity(scip, ub));
11944 
11945  /* update residual activities */
11946  if( vals[w] > 0 )
11947  {
11948  tmpmaxactsub += ub * vals[w];
11949  tmpminactsub += lb * vals[w];
11950  }
11951  else
11952  {
11953  tmpmaxactsub += lb * vals[w];
11954  tmpminactsub += ub * vals[w];
11955  }
11956  assert(tmpmaxactsub >= tmpminactsub);
11957  }
11958 
11959  if( hasrhs )
11960  {
11961  assert(offsetv == -1);
11962 
11963  /* determine the remainder of the right hand side and the gcd */
11964  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11965  }
11966  else
11967  {
11968  /* determine the remainder of the left hand side and the gcd */
11969  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11970  if( SCIPisZero(scip, siderest) )
11971  siderest = gcd;
11972  }
11973 
11974  /* is the redundancy really fulfilled */
11975  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11976  (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11977 #endif
11978 
11979  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11980  nvars - v, SCIPconsGetName(cons));
11981 
11982  /* remove redundant variables */
11983  for( w = nvars - 1; w >= v; --w )
11984  {
11985  SCIP_CALL( delCoefPos(scip, cons, w) );
11986  }
11987  (*nchgcoefs) += (nvars - v);
11988 
11989  assert(w >= 0);
11990 
11991  oldcoef = vals[w];
11992 
11993  /* normalize constraint */
11994  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11995  assert(vars == consdata->vars);
11996  assert(vals == consdata->vals);
11997  assert(w < consdata->nvars);
11998 
11999  if( *infeasible )
12000  return SCIP_OKAY;
12001 
12002  /* compute new greatest common divisor due to normalization */
12003  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12004  assert(gcd >= 1);
12005 
12006  /* update side */
12007  if( hasrhs )
12008  {
12009  /* replace old with new right hand side */
12010  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12011  rhs = consdata->rhs;
12012  }
12013  else
12014  {
12015  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12016  {
12017  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12018  lhs = consdata->lhs;
12019  }
12020  else
12021  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12022  }
12023  ++(*nchgsides);
12024 
12025  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12026  assert(!haslhs || !SCIPisNegative(scip, lhs));
12027 
12028  /* get new constraint data */
12029  nvars = consdata->nvars;
12030  assert(nvars > 0);
12031 
12032  allcoefintegral = TRUE;
12033 
12034 #ifndef NDEBUG
12035  /* check integrality */
12036  for( w = offsetv + 1; w < nvars; ++w )
12037  {
12038  assert(SCIPisIntegral(scip, vals[w]));
12039  }
12040 #endif
12041  SCIPdebugPrintCons(scip, cons, NULL);
12042  }
12043 
12044  /* try to find a better gcd, when having large coefficients */
12045  if( offsetv >= 0 && gcd == 1 )
12046  {
12047  /* calculate greatest common divisor for all general variables */
12048  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12049 
12050  if( gcd > 1 )
12051  {
12052  gcd = -1;
12053  candpos = -1;
12054 
12055  for( v = nvars - 1; v > offsetv; --v )
12056  {
12057  assert(!SCIPisZero(scip, vals[v]));
12058  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
12059  break;
12060 
12061  if( !SCIPisIntegral(scip, vals[v]) )
12062  {
12063  allcoefintegral = FALSE;
12064  break;
12065  }
12066 
12067  oldgcd = gcd;
12068 
12069  if( gcd == -1 )
12070  {
12071  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12072  assert(gcd >= 1);
12073  }
12074  else
12075  {
12076  /* calculate greatest common divisor for all general and binary variables */
12077  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12078  }
12079 
12080  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12081  * can stop searching
12082  */
12083  if( gcd == 1 )
12084  {
12085  if( !SCIPvarIsBinary(vars[v]) )
12086  break;
12087 
12088  /* found candidate */
12089  if( candpos == -1 )
12090  {
12091  gcd = oldgcd;
12092  candpos = v;
12093  }
12094  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12095  else
12096  break;
12097  }
12098  }
12099  assert(v > offsetv || candpos > offsetv);
12100  }
12101  else
12102  candpos = -1;
12103  }
12104  else
12105  candpos = nvars - 1;
12106 
12107  /* check last coefficient for integrality */
12108  if( gcd > 1 && allcoefintegral && !redundant )
12109  {
12110  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12111  allcoefintegral = FALSE;
12112  }
12113 
12114  /* check for further necessary coefficient adjustments */
12115  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12116  {
12117  assert(offsetv + 1 < nvars);
12118  assert(0 <= candpos && candpos < nvars);
12119 
12120  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12121  {
12122  SCIP_Bool notchangable = FALSE;
12123 
12124 #ifndef NDEBUG
12125  /* check integrality */
12126  for( w = offsetv + 1; w < nvars; ++w )
12127  {
12128  assert(SCIPisIntegral(scip, vals[w]));
12129  }
12130 #endif
12131 
12132  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12133  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12134  {
12135  /* determine the remainder of the side and the gcd */
12136  if( hasrhs )
12137  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12138  else
12139  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12140  assert(rest >= 0);
12141  assert(rest < gcd);
12142 
12143  /* determine the remainder of the coefficient candidate and the gcd */
12144  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12145  assert(restcoef >= 1);
12146  assert(restcoef < gcd);
12147 
12148  if( hasrhs )
12149  {
12150  /* calculate new coefficient */
12151  if( restcoef > rest )
12152  newcoef = vals[candpos] - restcoef + gcd;
12153  else
12154  newcoef = vals[candpos] - restcoef;
12155  }
12156  else
12157  {
12158  /* calculate new coefficient */
12159  if( rest == 0 || restcoef < rest )
12160  newcoef = vals[candpos] - restcoef;
12161  else
12162  newcoef = vals[candpos] - restcoef + gcd;
12163  }
12164 
12165  /* done */
12166 
12167  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12168  * another with the big coefficient was set to 1
12169  */
12170  if( hasrhs && SCIPisZero(scip, newcoef) )
12171  {
12172  notchangable = TRUE;
12173  }
12174  else if( SCIPisZero(scip, newcoef) )
12175  {
12176  /* delete old redundant coefficient */
12177  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12178  ++(*nchgcoefs);
12179  }
12180  else
12181  {
12182  /* replace old with new coefficient */
12183  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12184  ++(*nchgcoefs);
12185  }
12186  }
12187  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12188  {
12189  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12190  }
12191 
12192  /* correct side and big coefficients */
12193  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12194  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12195  {
12196  if( haslhs )
12197  {
12198  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12199 
12200  SCIP_CALL( chgLhs(scip, cons, newcoef) );
12201  ++(*nchgsides);
12202  }
12203  else
12204  {
12205  assert(hasrhs);
12206  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12207 
12208  SCIP_CALL( chgRhs(scip, cons, newcoef) );
12209  ++(*nchgsides);
12210  }
12211 
12212  /* correct coefficients up front */
12213  for( w = offsetv; w >= 0; --w )
12214  {
12215  assert(vals[w] > 0);
12216 
12217  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12218  }
12219  (*nchgcoefs) += (offsetv + 1);
12220  }
12221 
12222  if( !notchangable )
12223  {
12224  /* normalize constraint */
12225  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12226  assert(vars == consdata->vars);
12227  assert(vals == consdata->vals);
12228 
12229  if( *infeasible )
12230  return SCIP_OKAY;
12231 
12232  /* get new constraint data */
12233  nvars = consdata->nvars;
12234  assert(nvars >= 2);
12235 
12236  SCIPdebugPrintCons(scip, cons, NULL);
12237 
12238  lhs = consdata->lhs;
12239  rhs = consdata->rhs;
12240  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12241  assert(!haslhs || !SCIPisNegative(scip, lhs));
12242  }
12243  }
12244  }
12245  }
12246 
12247  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12248  /* no continuous variables are left over */
12249  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12250  return SCIP_OKAY;
12251 
12252  onlybin = TRUE;
12253  allcoefintegral = TRUE;
12254  /* check if all variables are of binary type */
12255  for( v = nvars - 1; v >= 0; --v )
12256  {
12257  if( !SCIPvarIsBinary(vars[v]) )
12258  onlybin = FALSE;
12259  if( !SCIPisIntegral(scip, vals[v]) )
12260  allcoefintegral = FALSE;
12261  }
12262 
12263  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12264  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12265  *
12266  * @todo there are some steps missing ....
12267  */
12268  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12269  {
12270  SCIP_Real val;
12271  SCIP_Real newval;
12272  SCIP_Real frac = 0.0;
12273  SCIP_Bool found = FALSE;
12274 
12275  if( hasrhs )
12276  {
12277  if( allcoefintegral )
12278  {
12279  /* replace old with new right hand side */
12280  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12281  ++(*nchgsides);
12282  }
12283  else
12284  {
12285  siderest = rhs - SCIPfloor(scip, rhs);
12286 
12287  /* try to round down all non-integral coefficients */
12288  for( v = nvars - 1; v >= 0; --v )
12289  {
12290  val = vals[v];
12291 
12292  /* add up all possible fractional parts */
12293  if( !SCIPisIntegral(scip, val) )
12294  {
12295  lb = SCIPvarGetLbGlobal(vars[v]);
12296  ub = SCIPvarGetUbGlobal(vars[v]);
12297 
12298  /* at least one bound need to be at zero */
12299  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12300  return SCIP_OKAY;
12301 
12302  /* swap bounds for 'standard' form */
12303  if( !SCIPisFeasZero(scip, lb) )
12304  {
12305  ub = lb;
12306  val *= -1;
12307  }
12308 
12309  found = TRUE;
12310 
12311  frac += (val - SCIPfloor(scip, val)) * ub;
12312 
12313  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12314  *
12315  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12316  * x3, x4 set to 1 would be infeasible but feasible after flooring
12317  */
12318  if( SCIPisGT(scip, frac, siderest) )
12319  return SCIP_OKAY;
12320  }
12321  }
12322  assert(v == -1);
12323 
12324  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12325 
12326  /* round rhs and coefficients to integral values */
12327  if( found )
12328  {
12329  for( v = nvars - 1; v >= 0; --v )
12330  {
12331  val = vals[v];
12332 
12333  /* add the whole fractional part */
12334  if( !SCIPisIntegral(scip, val) )
12335  {
12336  lb = SCIPvarGetLbGlobal(vars[v]);
12337 
12338  if( SCIPisFeasZero(scip, lb) )
12339  newval = SCIPfloor(scip, val);
12340  else
12341  newval = SCIPceil(scip, val);
12342 
12343  if( SCIPisZero(scip, newval) )
12344  {
12345  /* delete old redundant coefficient */
12346  SCIP_CALL( delCoefPos(scip, cons, v) );
12347  ++(*nchgcoefs);
12348  }
12349  else
12350  {
12351  /* replace old with new coefficient */
12352  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12353  ++(*nchgcoefs);
12354  }
12355  }
12356  }
12357  }
12358 
12359  /* replace old with new right hand side */
12360  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12361  ++(*nchgsides);
12362  }
12363  }
12364  else
12365  {
12366  if( allcoefintegral )
12367  {
12368  /* replace old with new left hand side */
12369  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12370  ++(*nchgsides);
12371  }
12372  else
12373  {
12374  /* cannot floor left hand side to zero */
12375  if( SCIPisLT(scip, lhs, 1.0) )
12376  return SCIP_OKAY;
12377 
12378  siderest = lhs - SCIPfloor(scip, lhs);
12379 
12380  /* try to round down all non-integral coefficients */
12381  for( v = nvars - 1; v >= 0; --v )
12382  {
12383  val = vals[v];
12384 
12385  /* add up all possible fractional parts */
12386  if( !SCIPisIntegral(scip, val) )
12387  {
12388  lb = SCIPvarGetLbGlobal(vars[v]);
12389  ub = SCIPvarGetUbGlobal(vars[v]);
12390 
12391  /* at least one bound need to be at zero */
12392  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12393  return SCIP_OKAY;
12394 
12395  /* swap bounds for 'standard' form */
12396  if( !SCIPisFeasZero(scip, lb) )
12397  {
12398  ub = lb;
12399  val *= -1;
12400  }
12401 
12402  /* cannot floor to zero */
12403  if( SCIPisLT(scip, val, 1.0) )
12404  return SCIP_OKAY;
12405 
12406  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12407  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12408  return SCIP_OKAY;
12409 
12410  found = TRUE;
12411 
12412  frac += (val - SCIPfloor(scip, val)) * ub;
12413 
12414  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12415  * fractional parts of the variables, we cannot tighten the coefficients
12416  *
12417  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12418  * x2-x4 set to 1 would be feasible but not after flooring
12419  */
12420  if( SCIPisGE(scip, frac, 1 + siderest) )
12421  return SCIP_OKAY;
12422  }
12423  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12424  else
12425  return SCIP_OKAY;
12426  }
12427  assert(v == -1);
12428 
12429  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12430 
12431  /* round lhs and coefficients to integral values */
12432  if( found )
12433  {
12434  for( v = nvars - 1; v >= 0; --v )
12435  {
12436  val = vals[v];
12437 
12438  /* add the whole fractional part */
12439  if( !SCIPisIntegral(scip, val) )
12440  {
12441  lb = SCIPvarGetLbGlobal(vars[v]);
12442 
12443  if( SCIPisFeasZero(scip, lb) )
12444  newval = SCIPfloor(scip, val);
12445  else
12446  newval = SCIPceil(scip, val);
12447 
12448  if( SCIPisZero(scip, newval) )
12449  {
12450  /* delete old redundant coefficient */
12451  SCIP_CALL( delCoefPos(scip, cons, v) );
12452  ++(*nchgcoefs);
12453  }
12454  else
12455  {
12456  /* replace old with new coefficient */
12457  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12458  ++(*nchgcoefs);
12459  }
12460  }
12461  }
12462  }
12463 
12464  /* replace old with new left hand side */
12465  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12466  ++(*nchgsides);
12467  }
12468  }
12469 
12470  /* normalize constraint */
12471  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12472  assert(vars == consdata->vars);
12473  assert(vals == consdata->vals);
12474 
12475  if( *infeasible )
12476  return SCIP_OKAY;
12477 
12478  rhs = consdata->rhs;
12479  lhs = consdata->lhs;
12480 
12481  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12482  assert(!haslhs || !SCIPisNegative(scip, lhs));
12483 
12484  SCIPdebugPrintCons(scip, cons, NULL);
12485 
12486  nvars = consdata->nvars;
12487  if( nvars < 2 )
12488  return SCIP_OKAY;
12489 
12490  allcoefintegral = TRUE;
12491 #ifndef NDEBUG
12492  /* debug check if all coefficients are really integral */
12493  for( v = nvars - 1; v >= 0; --v )
12494  assert(SCIPisIntegral(scip, vals[v]));
12495 #endif
12496  }
12497 
12498  /* @todo following can also work on non integral coefficients, need more investigation */
12499  /* only check constraints with integral coefficients on all integral variables */
12500  if( !allcoefintegral )
12501  return SCIP_OKAY;
12502 
12503  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12504  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12505  return SCIP_OKAY;
12506 
12507  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12508  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12509  return SCIP_OKAY;
12510 
12511  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12512  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12513  return SCIP_OKAY;
12514 
12515  assert(nvars >= 2);
12516 
12517  /* start gcd procedure for all variables */
12518  do
12519  {
12520  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12521  SCIPdebug( oldnchgsides = *nchgsides; )
12522 
12523  /* stop if we have two coeffcients which are one in absolute value */
12524  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12525  return SCIP_OKAY;
12526 
12527  gcd = -1;
12528 
12529  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12530  * because coefficients of non-binary variables might have changed to zero */
12531  if( !onlybin )
12532  {
12533  foundbin = -1;
12534  onlybin = TRUE;
12535 
12536  for( v = nvars - 1; v >= 0; --v )
12537  {
12538  assert(!SCIPisZero(scip, vals[v]));
12539  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12540 
12541  if( SCIPvarIsBinary(vars[v]) )
12542  {
12543  if( foundbin == -1 )
12544  foundbin = v;
12545  continue;
12546  }
12547  else
12548  onlybin = FALSE;
12549 
12550  absval = REALABS(vals[v]);
12551  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12552  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12553  */
12554  assert(SCIPisFeasIntegral(scip, absval));
12555 
12556  if( gcd == -1 )
12557  {
12558  gcd = (SCIP_Longint)(absval + feastol);
12559  assert(gcd >= 1);
12560  }
12561  else
12562  {
12563  /* calculate greatest common divisor for all general variables */
12564  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12565  }
12566  if( gcd == 1 )
12567  break;
12568  }
12569  }
12570  else
12571  foundbin = nvars - 1;
12572 
12573  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12574  if( gcd == 1 || foundbin == -1)
12575  return SCIP_OKAY;
12576 
12577  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12578 
12579  candpos = -1;
12580  candpos2 = -1;
12581 
12582  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12583  * change the coefficient
12584  */
12585  for( v = foundbin; v >= 0; --v )
12586  {
12587  if( onlybin || SCIPvarIsBinary(vars[v]) )
12588  {
12589  absval = REALABS(vals[v]);
12590  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12591  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12592  */
12593  assert(SCIPisFeasIntegral(scip, absval));
12594 
12595  oldgcd = gcd;
12596 
12597  if( gcd == -1 )
12598  {
12599  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12600  assert(gcd >= 1);
12601  }
12602  else
12603  {
12604  /* calculate greatest common divisor for all general and binary variables */
12605  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12606  }
12607 
12608  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12609  * can terminate
12610  */
12611  if( gcd == 1 )
12612  {
12613  /* found candidate */
12614  if( candpos == -1 )
12615  {
12616  gcd = oldgcd;
12617  candpos = v;
12618 
12619  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12620  * the coefficient change
12621  */
12622  if( onlybin && v == foundbin - 1 )
12623  candpos2 = foundbin;
12624  }
12625  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12626  else
12627  {
12628  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12629  {
12630  assert(candpos2 == nvars - 1);
12631 
12632  /* take new candidates */
12633  candpos = candpos2;
12634 
12635  /* recalculate gcd from scratch */
12636  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12637  assert(gcd >= 1);
12638 
12639  /* calculate greatest common divisor for all general and binary variables */
12640  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12641  if( gcd == 1 )
12642  return SCIP_OKAY;
12643  }
12644  else
12645  /* cannot determine a possible coefficient for reduction */
12646  return SCIP_OKAY;
12647  }
12648  }
12649  }
12650  }
12651  assert(gcd >= 2);
12652 
12653  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12654  * further
12655  */
12656  assert(candpos >= 0 && candpos < nvars);
12657 
12658  /* all variables and all coefficients are integral, so the side should be too */
12659  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12660 
12661  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12662  * @see normalizeCons()
12663  */
12664  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12665  assert(!haslhs || !SCIPisNegative(scip, lhs));
12666 
12667  /* determine the remainder of the side and the gcd */
12668  if( hasrhs )
12669  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12670  else
12671  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12672  assert(rest >= 0);
12673  assert(rest < gcd);
12674 
12675  /* determine the remainder of the coefficient candidate and the gcd */
12676  if( vals[candpos] < 0 )
12677  {
12678  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12679  assert(restcoef <= -1);
12680  restcoef += gcd;
12681  }
12682  else
12683  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12684  assert(restcoef >= 1);
12685  assert(restcoef < gcd);
12686 
12687  if( hasrhs )
12688  {
12689  if( rest > 0 )
12690  {
12691  /* replace old with new right hand side */
12692  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12693  ++(*nchgsides);
12694  }
12695 
12696  /* calculate new coefficient */
12697  if( restcoef > rest )
12698  newcoef = vals[candpos] - restcoef + gcd;
12699  else
12700  newcoef = vals[candpos] - restcoef;
12701  }
12702  else
12703  {
12704  if( rest > 0 )
12705  {
12706  /* replace old with new left hand side */
12707  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12708  ++(*nchgsides);
12709  }
12710 
12711  /* calculate new coefficient */
12712  if( rest == 0 || restcoef < rest )
12713  newcoef = vals[candpos] - restcoef;
12714  else
12715  newcoef = vals[candpos] - restcoef + gcd;
12716  }
12717  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12718 
12719  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));
12720 
12721  if( SCIPisZero(scip, newcoef) )
12722  {
12723  /* delete redundant coefficient */
12724  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12725  }
12726  else
12727  {
12728  /* replace old with new coefficient */
12729  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12730  }
12731  ++(*nchgcoefs);
12732 
12733  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12734  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12735  assert(vars == consdata->vars);
12736  assert(vals == consdata->vals);
12737 
12738  if( *infeasible )
12739  return SCIP_OKAY;
12740 
12741  SCIPdebugPrintCons(scip, cons, NULL);
12742 
12743  rhs = consdata->rhs;
12744  lhs = consdata->lhs;
12745  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12746  assert(!haslhs || !SCIPisNegative(scip, lhs));
12747 
12748  nvars = consdata->nvars;
12749 
12750  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));
12751  }
12752  while( nvars >= 2 );
12753 
12754  return SCIP_OKAY;
12755 }
12756 
12757 
12758 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12759  * cons0 := a * cons0 + b * cons1,
12760  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12761  * for numerical stability, we will only accept integral a and b;
12762  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12763  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12764  */
12765 static
12767  SCIP* scip, /**< SCIP data structure */
12768  SCIP_CONS* cons0, /**< (in)equality to modify */
12769  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12770  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12771  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12772  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12773  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12774  int nvarscommon, /**< number of variables, that appear in both constraints */
12775  int commonidxweight, /**< variable weight sum of common variables */
12776  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12777  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12778  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12779  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12780  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12781  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12782  )
12783 {
12784  SCIP_CONSDATA* consdata0;
12785  SCIP_CONSDATA* consdata1;
12786  SCIP_Real a;
12787  SCIP_Real b;
12788  SCIP_Real aggrcoef;
12789  SCIP_Real scalarsum;
12790  SCIP_Real bestscalarsum;
12791  SCIP_Bool betterscalarsum;
12792  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12793  int varweight;
12794  int nvars;
12795  int bestvarweight;
12796  int bestnvars;
12797  int bestv;
12798  int v;
12799  int i;
12800 
12801  assert(scip != NULL);
12802  assert(cons0 != NULL);
12803  assert(cons1 != NULL);
12804  assert(commonidx0 != NULL);
12805  assert(commonidx1 != NULL);
12806  assert(diffidx0minus1 != NULL);
12807  assert(diffidx1minus0 != NULL);
12808  assert(nvarscommon >= 1);
12809  assert(commonidxweight >= nvarscommon);
12810  assert(nchgcoefs != NULL);
12811  assert(aggregated != NULL);
12812 
12813  assert(SCIPconsIsActive(cons0));
12814  assert(SCIPconsIsActive(cons1));
12815 
12816  *infeasible = FALSE;
12817 
12818  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12819 
12820  /* cons0 is an (in)equality */
12821  consdata0 = SCIPconsGetData(cons0);
12822  assert(consdata0 != NULL);
12823  assert(consdata0->nvars >= 1);
12824  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12825  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12826 
12827  /* cons1 is an equality */
12828  consdata1 = SCIPconsGetData(cons1);
12829  assert(consdata1 != NULL);
12830  assert(consdata1->nvars >= 1);
12831  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12832  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12833 
12834  *aggregated = FALSE;
12835 
12836  /* search for the best common variable such that
12837  * val1[var] * consdata0 - val0[var] * consdata1
12838  * has least weighted number of variables
12839  */
12840  bestvarweight = commonidxweight + diffidx0minus1weight;
12841  bestnvars = consdata0->nvars;
12842  bestv = -1;
12843  bestscalarsum = 0.0;
12844  commonvarlindependent = TRUE;
12845  for( v = 0; v < nvarscommon; ++v )
12846  {
12847  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12848  a = consdata1->vals[commonidx1[v]];
12849  b = -consdata0->vals[commonidx0[v]];
12850 
12851  /* only try aggregation, if coefficients are integral (numerical stability) */
12852  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12853  {
12854  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12855  varweight = diffidx0minus1weight + diffidx1minus0weight;
12856  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12857  scalarsum = REALABS(a) + REALABS(b);
12858  betterscalarsum = (scalarsum < bestscalarsum);
12859  for( i = 0; i < nvarscommon
12860  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12861  {
12862  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12863  if( !SCIPisZero(scip, aggrcoef) )
12864  {
12865  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12866  nvars++;
12867  }
12868  }
12869  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12870  {
12871  bestv = v;
12872  bestvarweight = varweight;
12873  bestnvars = nvars;
12874  bestscalarsum = scalarsum;
12875  }
12876  }
12877 
12878  /* update commonvarlindependent flag, if still TRUE:
12879  * 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
12880  */
12881  if( commonvarlindependent && v > 0 )
12882  commonvarlindependent = SCIPisEQ(scip,
12883  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12884  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12885  }
12886 
12887  /* if better aggregation was found, create new constraint and delete old one */
12888  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12889  {
12890  SCIP_CONS* newcons;
12891  SCIP_CONSDATA* newconsdata;
12892  SCIP_VAR** newvars;
12893  SCIP_Real* newvals;
12894  SCIP_Real newlhs;
12895  SCIP_Real newrhs;
12896  int newnvars;
12897 
12898  if( bestv != -1 )
12899  {
12900  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12901  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12902  {
12903  a = consdata1->vals[commonidx1[bestv]];
12904  b = -consdata0->vals[commonidx0[bestv]];
12905  }
12906  else
12907  {
12908  a = -consdata1->vals[commonidx1[bestv]];
12909  b = consdata0->vals[commonidx0[bestv]];
12910  }
12911  assert(SCIPisIntegral(scip, a));
12912  assert(SCIPisPositive(scip, a));
12913  assert(SCIPisIntegral(scip, b));
12914  assert(!SCIPisZero(scip, b));
12915  }
12916  else
12917  {
12918  assert(commonvarlindependent);
12919  if( consdata1->vals[commonidx1[0]] > 0.0 )
12920  {
12921  a = consdata1->vals[commonidx1[0]];
12922  b = -consdata0->vals[commonidx0[0]];
12923  }
12924  else
12925  {
12926  a = -consdata1->vals[commonidx1[0]];
12927  b = consdata0->vals[commonidx0[0]];
12928  }
12929  assert(SCIPisPositive(scip, a));
12930  assert(!SCIPisZero(scip, b));
12931 
12932  /* if a/b is integral, then we can easily choose integer multipliers */
12933  if( SCIPisIntegral(scip, a/b) )
12934  {
12935  if( a/b > 0 )
12936  {
12937  a /= b;
12938  b = 1.0;
12939  }
12940  else
12941  {
12942  a /= -b;
12943  b = -1.0;
12944  }
12945  }
12946 
12947  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12948  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12949  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12950  }
12951 
12952  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12953  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12954  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12955  SCIPdebugPrintCons(scip, cons0, NULL);
12956  SCIPdebugPrintCons(scip, cons1, NULL);
12957 
12958  /* get temporary memory for creating the new linear constraint */
12959  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12960  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12961 
12962  /* calculate the common coefficients, if we have not recognized linear dependency */
12963  newnvars = 0;
12964  if( !commonvarlindependent )
12965  {
12966  for( i = 0; i < nvarscommon; ++i )
12967  {
12968  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12969  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12970 
12971  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12972  if( !SCIPisZero(scip, aggrcoef) )
12973  {
12974  assert(newnvars < bestnvars);
12975  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12976  newvals[newnvars] = aggrcoef;
12977  newnvars++;
12978  }
12979  }
12980  }
12981  else
12982  {
12983  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12984 #ifndef NDEBUG
12985  for( i = 0; i < nvarscommon; ++i )
12986  {
12987  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12988  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12989 
12990  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12991  assert(SCIPisZero(scip, aggrcoef));
12992  }
12993 #endif
12994  }
12995 
12996  /* calculate the coefficients appearing in cons0 but not in cons1 */
12997  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12998  {
12999  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13000 
13001  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13002  assert(!SCIPisZero(scip, aggrcoef));
13003  assert(newnvars < bestnvars);
13004  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13005  newvals[newnvars] = aggrcoef;
13006  newnvars++;
13007  }
13008 
13009  /* calculate the coefficients appearing in cons1 but not in cons0 */
13010  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13011  {
13012  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13013 
13014  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13015  assert(!SCIPisZero(scip, aggrcoef));
13016  assert(newnvars < bestnvars);
13017  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13018  newvals[newnvars] = aggrcoef;
13019  newnvars++;
13020  }
13021  assert(newnvars == bestnvars);
13022 
13023  /* calculate the new left and right hand side of the (in)equality */
13024  assert(!SCIPisInfinity(scip, -consdata1->lhs));
13025  assert(!SCIPisInfinity(scip, consdata1->rhs));
13026  if( SCIPisInfinity(scip, -consdata0->lhs) )
13027  newlhs = -SCIPinfinity(scip);
13028  else
13029  newlhs = a * consdata0->lhs + b * consdata1->lhs;
13030  if( SCIPisInfinity(scip, consdata0->rhs) )
13031  newrhs = SCIPinfinity(scip);
13032  else
13033  newrhs = a * consdata0->rhs + b * consdata1->rhs;
13034 
13035  /* create the new linear constraint */
13036  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13038  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
13039  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
13041 
13042  newconsdata = SCIPconsGetData(newcons);
13043  assert(newconsdata != NULL);
13044 
13045  /* copy the upgraded flag from the old cons0 to the new constraint */
13046  newconsdata->upgraded = consdata0->upgraded;
13047 
13048  /* normalize the new constraint */
13049  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13050 
13051  if( *infeasible )
13052  goto TERMINATE;
13053 
13054  /* check, if we really want to use the new constraint instead of the old one:
13055  * use the new one, if the maximum norm doesn't grow too much
13056  */
13057  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13058  {
13059  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13060  SCIPdebugPrintCons(scip, newcons, NULL);
13061 
13062  /* update the statistics: we changed all coefficients */
13063  if( !consdata0->upgraded )
13064  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13065  *aggregated = TRUE;
13066 
13067  /* delete the old constraint, and add the new linear constraint to the problem */
13068  SCIP_CALL( SCIPdelCons(scip, cons0) );
13069  SCIP_CALL( SCIPaddCons(scip, newcons) );
13070  }
13071 
13072  TERMINATE:
13073  /* release the new constraint */
13074  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13075 
13076  /* free temporary memory */
13077  SCIPfreeBufferArray(scip, &newvals);
13078  SCIPfreeBufferArray(scip, &newvars);
13079  }
13080 
13081  return SCIP_OKAY;
13082 }
13083 
13084 /** gets the key of the given element */
13085 static
13086 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13087 { /*lint --e{715}*/
13088  /* the key is the element itself */
13089  return elem;
13090 }
13091 
13092 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13093  * coefficients are either equal or negated
13094  */
13095 static
13096 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13097 {
13098  SCIP* scip;
13099  SCIP_CONSDATA* consdata1;
13100  SCIP_CONSDATA* consdata2;
13101  SCIP_Real cons1scale;
13102  SCIP_Real cons2scale;
13103  int i;
13104 
13105  assert(key1 != NULL);
13106  assert(key2 != NULL);
13107  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13108  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13109  assert(consdata1->indexsorted);
13110  assert(consdata2->indexsorted);
13111 
13112  scip = (SCIP*)userptr;
13113  assert(scip != NULL);
13114 
13115  /* if it is the same constraint we dont need to check anything */
13116  if( key1 == key2 )
13117  return TRUE;
13118 
13119  /* checks trivial case */
13120  if( consdata1->nvars != consdata2->nvars )
13121  return FALSE;
13122 
13123  /* tests if variables are equal */
13124  for( i = 0; i < consdata1->nvars; ++i )
13125  {
13126  if( consdata1->vars[i] != consdata2->vars[i] )
13127  {
13128  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13129  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13130  return FALSE;
13131  }
13132  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13133  }
13134 
13135  /* compute scale before comparing coefficients of constraints */
13136  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13137  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13138 
13139  /* tests if coefficients are equal with the computed scale */
13140  for( i = 0; i < consdata1->nvars; ++i )
13141  {
13142  SCIP_Real val1;
13143  SCIP_Real val2;
13144 
13145  val1 = consdata1->vals[i] * cons1scale;
13146  val2 = consdata2->vals[i] * cons2scale;
13147 
13148  if( !SCIPisEQ(scip, val1, val2) )
13149  return FALSE;
13150  }
13151 
13152  return TRUE;
13153 }
13154 
13155 /** returns the hash value of the key */
13156 static
13157 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13158 {
13159  SCIP_CONSDATA* consdata;
13160  int minidx;
13161  int mididx;
13162  int maxidx;
13163  SCIP_Real scale;
13164 #ifndef NDEBUG
13165  SCIP* scip;
13166 
13167  scip = (SCIP*)userptr;
13168  assert(scip != NULL);
13169 #endif
13170 
13171  assert(key != NULL);
13172  consdata = SCIPconsGetData((SCIP_CONS*)key);
13173  assert(consdata != NULL);
13174  assert(consdata->nvars > 0);
13175 
13176  assert(consdata->indexsorted);
13177 
13178  minidx = SCIPvarGetIndex(consdata->vars[0]);
13179  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13180  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13181  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13182 
13183  /* using only the variable indices as hash, since the values are compared by epsilon */
13184  return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13185  mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13186  maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13187 }
13188 
13189 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13190  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13191  */
13192 static
13193 unsigned int getParallelConsKey(
13194  SCIP_CONS* cons /**< linear constraint */
13195  )
13196 {
13197  SCIP_CONSDATA* consdata;
13198 
13199  assert(cons != NULL);
13200 
13201  consdata = SCIPconsGetData(cons);
13202  assert(consdata != NULL);
13203 
13204  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13205 }
13206 
13207 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13208  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13209  * and all others are removed from the hashtable and stored in the given array
13210  */
13211 static
13213  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13214  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13215  * upon return will contain the constraint that should be kept */
13216  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13217  * these constraints where removed from the hashtable */
13218  int* nparallelconss /**< pointer to return number of parallel constraints */
13219  )
13220 {
13221  SCIP_CONS* parallelcons;
13222  unsigned int querykey;
13223 
13224  *nparallelconss = 0;
13225  querykey = getParallelConsKey(*querycons);
13226 
13227  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13228  {
13229  unsigned int conskey = getParallelConsKey(parallelcons);
13230 
13231  if( conskey < querykey )
13232  {
13233  parallelconss[(*nparallelconss)++] = *querycons;
13234  *querycons = parallelcons;
13235  querykey = conskey;
13236  }
13237  else
13238  {
13239  parallelconss[(*nparallelconss)++] = parallelcons;
13240  }
13241 
13242  /* if the constraint that just came out of the hash table is the one that is kept,
13243  * we do not need to look into the hashtable again, since the invariant is that
13244  * in the hashtable only pair-wise non-parallel constraints are contained.
13245  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13246  * could be contained due to non-transitivity of the equality comparison.
13247  * Also we can return immediately, since parallelcons is already contained in the
13248  * hashtable and we do not need to remove and reinsert it.
13249  */
13250  if( *querycons == parallelcons )
13251  return SCIP_OKAY;
13252 
13253  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13254  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13255  }
13256 
13257  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13258  * comnpares equal to querycons at this point
13259  */
13260 #ifndef NDEBUG
13261  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13262 #else
13263  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13264 #endif
13265 
13266  return SCIP_OKAY;
13267 }
13268 
13269 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13270  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13271  */
13272 static
13274  SCIP* scip, /**< SCIP data structure */
13275  BMS_BLKMEM* blkmem, /**< block memory */
13276  SCIP_CONS** conss, /**< constraint set */
13277  int nconss, /**< number of constraints in constraint set */
13278  int* firstchange, /**< pointer to store first changed constraint */
13279  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13280  int* ndelconss, /**< pointer to count number of deleted constraints */
13281  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13282  )
13283 {
13284  SCIP_HASHTABLE* hashtable;
13285  SCIP_CONS** parallelconss;
13286  int nparallelconss;
13287  int hashtablesize;
13288  int c;
13289 
13290  assert(scip != NULL);
13291  assert(blkmem != NULL);
13292  assert(conss != NULL);
13293  assert(firstchange != NULL);
13294  assert(cutoff != NULL);
13295  assert(ndelconss != NULL);
13296  assert(nchgsides != NULL);
13297 
13298  /* create a hash table for the constraint set */
13299  hashtablesize = nconss;
13300  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13301  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13302 
13303  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13304 
13305  /* check all constraints in the given set for redundancy */
13306  for( c = 0; c < nconss; ++c )
13307  {
13308  SCIP_CONS* cons0;
13309  SCIP_CONSDATA* consdata0;
13310 
13311  cons0 = conss[c];
13312 
13313  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13314  continue;
13315 
13316  /* check for interuption */
13317  if( c % 1000 == 0 && SCIPisStopped(scip) )
13318  break;
13319 
13320  /* sorts the constraint */
13321  consdata0 = SCIPconsGetData(cons0);
13322  assert(consdata0 != NULL);
13323  SCIP_CALL( consdataSort(scip, consdata0) );
13324  assert(consdata0->indexsorted);
13325 
13326  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13327  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13328  * first variable is positive
13329  * Also inserts cons0 into the hashtable.
13330  */
13331  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13332 
13333  if( nparallelconss != 0 )
13334  {
13335  SCIP_Real lhs;
13336  SCIP_Real rhs;
13337 
13338  int i;
13339 
13340  /* cons0 may have been changed in retrieveParallelConstraints() */
13341  consdata0 = SCIPconsGetData(cons0);
13342 
13343  lhs = consdata0->lhs;
13344  rhs = consdata0->rhs;
13345 
13346  for( i = 0; i < nparallelconss; ++i )
13347  {
13348  SCIP_CONS* consdel;
13349  SCIP_CONSDATA* consdatadel;
13350  SCIP_Real scale;
13351 
13352  consdel = parallelconss[i];
13353  consdatadel = SCIPconsGetData(consdel);
13354 
13355  assert(SCIPconsIsActive(consdel));
13356  assert(!SCIPconsIsModifiable(consdel));
13357 
13358  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13359  * delete old constraints afterwards
13360  */
13361  assert(consdatadel != NULL);
13362  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13363 
13364  assert(consdatadel->indexsorted);
13365  assert(consdata0->vars[0] == consdatadel->vars[0]);
13366 
13367  scale = consdata0->vals[0] / consdatadel->vals[0];
13368  assert(scale != 0.0);
13369 
13370  /* in debug mode, check that all coefficients are equal with respect to epsilon
13371  * if the constraints are in equilibrium scale
13372  */
13373 #ifndef NDEBUG
13374  {
13375  int k;
13376  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13377  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13378 
13379  for( k = 0; k < consdata0->nvars; ++k )
13380  {
13381  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13382  }
13383  }
13384 #endif
13385 
13386  if( scale > 0.0 )
13387  {
13388  /* the coefficients of both constraints are parallel with a positive scale */
13389  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13390  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13391  SCIPdebugPrintCons(scip, cons0, NULL);
13392  SCIPdebugPrintCons(scip, consdel, NULL);
13393 
13394  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13395  lhs = MAX(scale * consdatadel->lhs, lhs);
13396 
13397  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13398  rhs = MIN(scale * consdatadel->rhs, rhs);
13399  }
13400  else
13401  {
13402  /* the coefficients of both rows are negations */
13403  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13404  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13405  SCIPdebugPrintCons(scip, cons0, NULL);
13406  SCIPdebugPrintCons(scip, consdel, NULL);
13407 
13408  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13409  lhs = MAX(scale * consdatadel->rhs, lhs);
13410 
13411  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13412  rhs = MIN(scale * consdatadel->lhs, rhs);
13413  }
13414 
13415  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13416  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13417 
13418  /* delete consdel */
13419  assert( ! consdata0->upgraded || consdatadel->upgraded );
13420  SCIP_CALL( SCIPdelCons(scip, consdel) );
13421  if( !consdatadel->upgraded )
13422  (*ndelconss)++;
13423  }
13424 
13425  if( SCIPisFeasLT(scip, rhs, lhs) )
13426  {
13427  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13428  *cutoff = TRUE;
13429  break;
13430  }
13431 
13432  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13433  if( lhs > rhs )
13434  {
13435  rhs = (lhs + rhs)/2;
13436  lhs = rhs;
13437  }
13438 
13439  /* update lhs and rhs of cons0 */
13440  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13441  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13442 
13443  /* update the first changed constraint to begin the next aggregation round with */
13444  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13445  *firstchange = SCIPconsGetPos(cons0);
13446 
13447  assert(SCIPconsIsActive(cons0));
13448  }
13449  }
13450 #ifdef SCIP_MORE_DEBUG
13451  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13453 #endif
13454 
13455  SCIPfreeBufferArray(scip, &parallelconss);
13456 
13457  /* free hash table */
13458  SCIPhashtableFree(&hashtable);
13459 
13460  return SCIP_OKAY;
13461 }
13462 
13463 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13464  * and removes or changes constraint accordingly
13465  */
13466 static
13468  SCIP* scip, /**< SCIP data structure */
13469  SCIP_CONS** conss, /**< constraint set */
13470  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13471  int chkind, /**< index of constraint to check against all prior indices upto startind */
13472  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13473  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13474  int* ndelconss, /**< pointer to count number of deleted constraints */
13475  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13476  int* nchgcoefs /**< pointer to count number of changed coefficients */
13477  )
13478 {
13479  SCIP_CONS* cons0;
13480  SCIP_CONSDATA* consdata0;
13481  int* commonidx0;
13482  int* commonidx1;
13483  int* diffidx0minus1;
13484  int* diffidx1minus0;
13485  uint64_t possignature0;
13486  uint64_t negsignature0;
13487  SCIP_Bool cons0changed;
13488  SCIP_Bool cons0isequality;
13489  int diffidx1minus0size;
13490  int c;
13491  SCIP_Real cons0lhs;
13492  SCIP_Real cons0rhs;
13493  SCIP_Bool cons0upgraded;
13494 
13495  assert(scip != NULL);
13496  assert(conss != NULL);
13497  assert(firstchange <= chkind);
13498  assert(cutoff != NULL);
13499  assert(ndelconss != NULL);
13500  assert(nchgsides != NULL);
13501  assert(nchgcoefs != NULL);
13502 
13503  /* get the constraint to be checked against all prior constraints */
13504  cons0 = conss[chkind];
13505  assert(cons0 != NULL);
13506  assert(SCIPconsIsActive(cons0));
13507  assert(!SCIPconsIsModifiable(cons0));
13508 
13509  consdata0 = SCIPconsGetData(cons0);
13510  assert(consdata0 != NULL);
13511  assert(consdata0->nvars >= 1);
13512  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13513 
13514  /* sort the constraint */
13515  SCIP_CALL( consdataSort(scip, consdata0) );
13516 
13517  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13518  consdataCalcSignatures(consdata0);
13519  possignature0 = consdata0->possignature;
13520  negsignature0 = consdata0->negsignature;
13521 
13522  /* get temporary memory for indices of common variables */
13523  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13524  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13525  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13526  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13527  diffidx1minus0size = consdata0->nvars;
13528 
13529  cons0lhs = consdata0->lhs;
13530  cons0rhs = consdata0->rhs;
13531  cons0upgraded = consdata0->upgraded;
13532 
13533  /* check constraint against all prior constraints */
13534  cons0changed = consdata0->changed;
13535  consdata0->changed = FALSE;
13536  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13537  {
13538  SCIP_CONS* cons1;
13539  SCIP_CONSDATA* consdata1;
13540  uint64_t possignature1;
13541  uint64_t negsignature1;
13542  SCIP_Bool cons0dominateslhs;
13543  SCIP_Bool cons1dominateslhs;
13544  SCIP_Bool cons0dominatesrhs;
13545  SCIP_Bool cons1dominatesrhs;
13546  SCIP_Bool cons1isequality;
13547  SCIP_Bool coefsequal;
13548  SCIP_Bool coefsnegated;
13549  SCIP_Bool tryaggregation;
13550  int nvarscommon;
13551  int nvars0minus1;
13552  int nvars1minus0;
13553  int commonidxweight;
13554  int diffidx0minus1weight;
13555  int diffidx1minus0weight;
13556  int v0;
13557  int v1;
13558 
13559  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13560  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13561  assert(cons0upgraded == consdata0->upgraded);
13562 
13563  cons1 = conss[c];
13564 
13565  /* cons1 has become inactive during presolving of constraint pairs */
13566  if( cons1 == NULL )
13567  continue;
13568 
13569  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13570  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13571 
13572  consdata1 = SCIPconsGetData(cons1);
13573  assert(consdata1 != NULL);
13574 
13575  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13576  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13577  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13578 
13579  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13580  if( !cons0changed && !consdata1->changed )
13581  continue;
13582 
13583  /* if both constraints are already upgraded, skip the pair;
13584  * because changes on these constraints cannot be applied to the instance anymore */
13585  if( cons0upgraded && consdata1->upgraded )
13586  continue;
13587 
13588  assert(consdata1->nvars >= 1);
13589 
13590  /* sort the constraint */
13591  SCIP_CALL( consdataSort(scip, consdata1) );
13592 
13593  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13594  consdataCalcSignatures(consdata1);
13595  possignature1 = consdata1->possignature;
13596  negsignature1 = consdata1->negsignature;
13597 
13598  /* the signatures give a quick test to check for domination and equality of coefficients */
13599  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13600  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13601  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13602  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13603  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13604  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13605  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13606  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13607  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13608  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13609  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13610  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13611  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13612  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13613  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13614  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13615  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13616  && !coefsequal && !coefsnegated && !tryaggregation )
13617  continue;
13618 
13619  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13620  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13621  {
13622  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13623  diffidx1minus0size = consdata1->nvars;
13624  }
13625 
13626  /* check consdata0 against consdata1:
13627  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13628  * consdata0 dominates consdata1 w.r.t. left hand side
13629  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13630  * consdata0 dominates consdata1 w.r.t. right hand side
13631  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13632  * ranged row (or equality)
13633  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13634  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13635  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13636  * number of continuous and integer variables are preferred:
13637  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13638  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13639  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13640  * to be positive to not switch the sense of the (in)equality cons0
13641  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13642  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13643  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13644  * to be positive to not switch the sense of the (in)equality cons1
13645  */
13646 
13647  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13648  nvarscommon = 0;
13649  commonidxweight = 0;
13650  nvars0minus1 = 0;
13651  diffidx0minus1weight = 0;
13652  nvars1minus0 = 0;
13653  diffidx1minus0weight = 0;
13654  v0 = 0;
13655  v1 = 0;
13656  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13657  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13658  || coefsequal || coefsnegated || tryaggregation) )
13659  {
13660  SCIP_VAR* var;
13661  SCIP_Real val0;
13662  SCIP_Real val1;
13663  int varcmp;
13664 
13665  /* test, if variable appears in only one or in both constraints */
13666  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13667  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13668  else if( v0 < consdata0->nvars )
13669  varcmp = -1;
13670  else
13671  varcmp = +1;
13672 
13673  switch( varcmp )
13674  {
13675  case -1:
13676  /* variable doesn't appear in consdata1 */
13677  var = consdata0->vars[v0];
13678  val0 = consdata0->vals[v0];
13679  val1 = 0.0;
13680  if( tryaggregation )
13681  {
13682  diffidx0minus1[nvars0minus1] = v0;
13683  nvars0minus1++;
13684  diffidx0minus1weight += getVarWeight(var);
13685  }
13686  v0++;
13687  coefsequal = FALSE;
13688  coefsnegated = FALSE;
13689  break;
13690 
13691  case +1:
13692  /* variable doesn't appear in consdata0 */
13693  var = consdata1->vars[v1];
13694  val0 = 0.0;
13695  val1 = consdata1->vals[v1];
13696  if( tryaggregation )
13697  {
13698  diffidx1minus0[nvars1minus0] = v1;
13699  nvars1minus0++;
13700  diffidx1minus0weight += getVarWeight(var);
13701  }
13702  v1++;
13703  coefsequal = FALSE;
13704  coefsnegated = FALSE;
13705  break;
13706 
13707  case 0:
13708  /* variable appears in both constraints */
13709  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13710  var = consdata0->vars[v0];
13711  val0 = consdata0->vals[v0];
13712  val1 = consdata1->vals[v1];
13713  if( tryaggregation )
13714  {
13715  commonidx0[nvarscommon] = v0;
13716  commonidx1[nvarscommon] = v1;
13717  nvarscommon++;
13718  commonidxweight += getVarWeight(var);
13719  }
13720  v0++;
13721  v1++;
13722  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13723  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13724  break;
13725 
13726  default:
13727  SCIPerrorMessage("invalid comparison result\n");
13728  SCIPABORT();
13729  var = NULL;
13730  val0 = 0.0;
13731  val1 = 0.0;
13732  }
13733  assert(var != NULL);
13734 
13735  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13736  if( SCIPisGT(scip, val0, val1) )
13737  {
13738  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13739  {
13740  cons0dominatesrhs = FALSE;
13741  cons1dominateslhs = FALSE;
13742  }
13743  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13744  {
13745  cons0dominateslhs = FALSE;
13746  cons1dominatesrhs = FALSE;
13747  }
13748  }
13749  else if( SCIPisLT(scip, val0, val1) )
13750  {
13751  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13752  {
13753  cons0dominateslhs = FALSE;
13754  cons1dominatesrhs = FALSE;
13755  }
13756  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13757  {
13758  cons0dominatesrhs = FALSE;
13759  cons1dominateslhs = FALSE;
13760  }
13761  }
13762  }
13763 
13764  /* check for disaggregated ranged rows */
13765  if( coefsequal || coefsnegated )
13766  {
13767  SCIP_CONS* consstay;
13768  SCIP_CONS* consdel;
13769 #ifndef NDEBUG
13770  SCIP_CONSDATA* consdatastay;
13771 #endif
13772  SCIP_CONSDATA* consdatadel;
13773  SCIP_Real lhs;
13774  SCIP_Real rhs;
13775  int consinddel;
13776 
13777  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13778  * best left and right hand sides; delete the old constraints afterwards
13779  */
13780  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13781  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13782  SCIPdebugPrintCons(scip, cons0, NULL);
13783  SCIPdebugPrintCons(scip, cons1, NULL);
13784 
13785  if( coefsequal )
13786  {
13787  /* the coefficients of both rows are equal */
13788  lhs = MAX(consdata0->lhs, consdata1->lhs);
13789  rhs = MIN(consdata0->rhs, consdata1->rhs);
13790  }
13791  else
13792  {
13793  /* the coefficients of both rows are negations */
13794  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13795  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13796  }
13797  if( SCIPisFeasLT(scip, rhs, lhs) )
13798  {
13799  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13800  *cutoff = TRUE;
13801  break;
13802  }
13803 
13804  /* check which constraint has to stay;
13805  * changes applied to an upgraded constraint will not be considered in the instance */
13806  if( consdata0->upgraded )
13807  {
13808  assert(!consdata1->upgraded);
13809  consstay = cons1;
13810 #ifndef NDEBUG
13811  consdatastay = consdata1;
13812 #endif
13813 
13814  consdel = cons0;
13815  consdatadel = consdata0;
13816  consinddel = chkind;
13817  }
13818  else
13819  {
13820  consstay = cons0;
13821 #ifndef NDEBUG
13822  consdatastay = consdata0;
13823 #endif
13824 
13825  consdel = cons1;
13826  consdatadel = consdata1;
13827  consinddel = c;
13828  }
13829 
13830  /* update the sides of consstay */
13831  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13832  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13833  if( !consdata0->upgraded )
13834  {
13835  assert(consstay == cons0);
13836  cons0lhs = consdata0->lhs;
13837  cons0rhs = consdata0->rhs;
13838  }
13839 
13840  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13841  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13842 
13843  assert( !consdatastay->upgraded );
13844  /* delete consdel */
13845  SCIP_CALL( SCIPdelCons(scip, consdel) );
13846  conss[consinddel] = NULL;
13847  if( !consdatadel->upgraded )
13848  (*ndelconss)++;
13849  continue;
13850  }
13851 
13852  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13853  * redundant
13854  */
13855  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13856  {
13857  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13858  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13859  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13860  SCIPdebugPrintCons(scip, cons0, NULL);
13861  SCIPdebugPrintCons(scip, cons1, NULL);
13862 
13863  /* check for infeasibility */
13864  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13865  {
13866  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13867  *cutoff = TRUE;
13868  break;
13869  }
13870 
13871  /* remove redundant left hand side */
13872  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13873  {
13874  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13875  cons0lhs = consdata0->lhs;
13876  cons0isequality = FALSE;
13877  if( !consdata0->upgraded )
13878  {
13879  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13880  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13881 
13882  (*nchgsides)++;
13883  }
13884  }
13885  }
13886  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13887  {
13888  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13889  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13890  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13891  SCIPdebugPrintCons(scip, cons1, NULL);
13892  SCIPdebugPrintCons(scip, cons0, NULL);
13893 
13894  /* check for infeasibility */
13895  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13896  {
13897  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13898  *cutoff = TRUE;
13899  break;
13900  }
13901 
13902  /* remove redundant left hand side */
13903  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13904  {
13905  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13906  cons1isequality = FALSE;
13907  if( !consdata1->upgraded )
13908  {
13909  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13910  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13911 
13912  (*nchgsides)++;
13913  }
13914  }
13915  }
13916  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13917  {
13918  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13919  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13920  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13921  SCIPdebugPrintCons(scip, cons0, NULL);
13922  SCIPdebugPrintCons(scip, cons1, NULL);
13923 
13924  /* check for infeasibility */
13925  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13926  {
13927  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13928  *cutoff = TRUE;
13929  break;
13930  }
13931 
13932  /* remove redundant right hand side */
13933  if( !SCIPisInfinity(scip, consdata0->rhs) )
13934  {
13935  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13936  cons0rhs = consdata0->rhs;
13937  cons0isequality = FALSE;
13938  if( !consdata0->upgraded )
13939  {
13940  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13941  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13942 
13943  (*nchgsides)++;
13944  }
13945  }
13946  }
13947  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13948  {
13949  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13950  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13951  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13952  SCIPdebugPrintCons(scip, cons1, NULL);
13953  SCIPdebugPrintCons(scip, cons0, NULL);
13954 
13955  /* check for infeasibility */
13956  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13957  {
13958  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13959  *cutoff = TRUE;
13960  break;
13961  }
13962 
13963  /* remove redundant right hand side */
13964  if( !SCIPisInfinity(scip, consdata1->rhs) )
13965  {
13966  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13967  cons1isequality = FALSE;
13968  if( !consdata1->upgraded )
13969  {
13970  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13971  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13972 
13973  (*nchgsides)++;
13974  }
13975  }
13976  }
13977 
13978  /* check for now redundant constraints */
13979  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13980  {
13981  /* consdata0 became redundant */
13982  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13983  SCIP_CALL( SCIPdelCons(scip, cons0) );
13984  conss[chkind] = NULL;
13985  if( !consdata0->upgraded )
13986  {
13987  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13988  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13989 
13990  (*ndelconss)++;
13991  }
13992  continue;
13993  }
13994  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13995  {
13996  /* consdata1 became redundant */
13997  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13998  SCIP_CALL( SCIPdelCons(scip, cons1) );
13999  conss[c] = NULL;
14000  if( !consdata1->upgraded )
14001  {
14002  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14003  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14004 
14005  (*ndelconss)++;
14006  }
14007  continue;
14008  }
14009 
14010  /* check, if we want to aggregate an (in)equality with an equality:
14011  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14012  */
14013  if( tryaggregation )
14014  {
14015  SCIP_Bool aggregated;
14016 
14017  assert(consdata0->nvars == nvarscommon + nvars0minus1);
14018  assert(consdata1->nvars == nvarscommon + nvars1minus0);
14019 
14020  aggregated = FALSE;
14021  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14022  {
14023  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14024  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14025  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14026  nchgcoefs, &aggregated, cutoff) );
14027 
14028  if( *cutoff )
14029  break;
14030 
14031  /* update array of active constraints */
14032  if( aggregated )
14033  {
14034  assert(!SCIPconsIsActive(cons0));
14035  assert(SCIPconsIsActive(cons1));
14036  conss[chkind] = NULL;
14037  }
14038  }
14039  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14040  {
14041  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14042  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14043  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14044  nchgcoefs, &aggregated, cutoff) );
14045 
14046  if( *cutoff )
14047  break;
14048 
14049  /* update array of active constraints */
14050  if( aggregated )
14051  {
14052  assert(!SCIPconsIsActive(cons1));
14053  assert(SCIPconsIsActive(cons0));
14054  conss[c] = NULL;
14055  }
14056  }
14057  }
14058  }
14059 
14060  /* free temporary memory */
14061  SCIPfreeBufferArray(scip, &diffidx1minus0);
14062  SCIPfreeBufferArray(scip, &diffidx0minus1);
14063  SCIPfreeBufferArray(scip, &commonidx1);
14064  SCIPfreeBufferArray(scip, &commonidx0);
14065 
14066  return SCIP_OKAY;
14067 }
14068 
14069 /** do stuffing presolving on a single constraint */
14070 static
14072  SCIP* scip, /**< SCIP data structure */
14073  SCIP_CONS* cons, /**< linear constraint */
14074  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14075  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14076  * constraints using the cheapest variable? */
14077  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14078  int* nfixedvars, /**< pointer to count the total number of fixed variables */
14079  int* nchgbds /**< pointer to count the total number of tightened bounds */
14080  )
14081 {
14082  SCIP_CONSDATA* consdata;
14083  SCIP_Real* ratios;
14084  int* varpos;
14085  SCIP_Bool* swapped;
14086  SCIP_VAR** vars;
14087  SCIP_Real* vals;
14088  SCIP_VAR* var;
14089  SCIP_Real lb;
14091  SCIP_Real minactivity;
14092  SCIP_Real maxactivity;
14093  SCIP_Real maxcondactivity;
14094  SCIP_Real mincondactivity;
14095  SCIP_Real rhs;
14096  SCIP_Real val;
14097  SCIP_Real obj;
14098  SCIP_Real factor;
14099  SCIP_Bool minactisrelax;
14100  SCIP_Bool maxactisrelax;
14101  SCIP_Bool isminsettoinfinity;
14102  SCIP_Bool ismaxsettoinfinity;
14103  SCIP_Bool tryfixing;
14104  int nsingletons;
14105  int idx;
14106  int v;
14107  int nvars;
14108 
14109  assert(scip != NULL);
14110  assert(cons != NULL);
14111  assert(nfixedvars != NULL);
14112 
14113  consdata = SCIPconsGetData(cons);
14114 
14115  /* we only want to run for inequalities */
14116  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14117  return SCIP_OKAY;
14118 
14119  if( singlevarstuffing )
14120  {
14121  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14122  &isminsettoinfinity, &ismaxsettoinfinity);
14123  }
14124  else
14125  {
14126  minactivity = SCIP_INVALID;
14127  maxactivity = SCIP_INVALID;
14128  isminsettoinfinity = FALSE;
14129  ismaxsettoinfinity = FALSE;
14130  }
14131 
14132  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14133  * the new maxactivity is minus the old minactivity then
14134  */
14135  if( SCIPisInfinity(scip, consdata->rhs) )
14136  {
14137  rhs = -consdata->lhs;
14138  factor = -1.0;
14139  maxactivity = -minactivity;
14140  ismaxsettoinfinity = isminsettoinfinity;
14141  }
14142  else
14143  {
14144  assert(SCIPisInfinity(scip, -consdata->lhs));
14145  rhs = consdata->rhs;
14146  factor = 1.0;
14147  }
14148 
14149  nvars = consdata->nvars;
14150  vars = consdata->vars;
14151  vals = consdata->vals;
14152 
14153  /* check for continuous singletons */
14154  if( singletonstuffing )
14155  {
14156  for( v = 0; v < nvars; ++v )
14157  {
14158  var = vars[v];
14159 
14162  break;
14163  }
14164  }
14165  else
14166  /* we don't want to go into the next block */
14167  v = nvars;
14168 
14169  /* a singleton was found -> perform singleton variable stuffing */
14170  if( v < nvars )
14171  {
14172  assert(singletonstuffing);
14173 
14174  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14175  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14176  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14177 
14178  tryfixing = TRUE;
14179  nsingletons = 0;
14180  mincondactivity = 0.0;
14181  maxcondactivity = 0.0;
14182 
14183  for( v = 0; v < nvars; ++v )
14184  {
14185  var = vars[v];
14186  lb = SCIPvarGetLbGlobal(var);
14187  ub = SCIPvarGetUbGlobal(var);
14188  obj = SCIPvarGetObj(var);
14189  val = factor * vals[v];
14190 
14191  assert(!SCIPisZero(scip, val));
14192 
14193  /* the variable is a singleton and continuous */
14196  {
14197  if( SCIPisNegative(scip, obj) && val > 0 )
14198  {
14199  /* case 1: obj < 0 and coef > 0 */
14200  if( SCIPisInfinity(scip, -lb) )
14201  {
14202  tryfixing = FALSE;
14203  break;
14204  }
14205 
14206  maxcondactivity += val * lb;
14207  mincondactivity += val * lb;
14208  swapped[v] = FALSE;
14209  ratios[nsingletons] = obj / val;
14210  varpos[nsingletons] = v;
14211  nsingletons++;
14212  }
14213  else if( SCIPisPositive(scip, obj) && val < 0 )
14214  {
14215  /* case 2: obj > 0 and coef < 0 */
14216  if( SCIPisInfinity(scip, ub) )
14217  {
14218  tryfixing = FALSE;
14219  break;
14220  }
14221  /* multiply column by (-1) to become case 1.
14222  * now bounds are swapped: ub := -lb, lb := -ub
14223  */
14224 
14225  maxcondactivity += val * ub;
14226  mincondactivity += val * ub;
14227  swapped[v] = TRUE;
14228  ratios[nsingletons] = obj / val;
14229  varpos[nsingletons] = v;
14230  nsingletons++;
14231  }
14232  else if( val > 0 )
14233  {
14234  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14235  * we only consider the lower bound for the constants
14236  */
14237  assert(!SCIPisNegative(scip, obj));
14238 
14239  if( SCIPisInfinity(scip, -lb) )
14240  {
14241  /* maybe unbounded */
14242  tryfixing = FALSE;
14243  break;
14244  }
14245 
14246  maxcondactivity += val * lb;
14247  mincondactivity += val * lb;
14248  }
14249  else
14250  {
14251  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14252  * we only consider the upper bound for the constants
14253  */
14254  assert(!SCIPisPositive(scip, obj));
14255  assert(val < 0);
14256 
14257  if( SCIPisInfinity(scip, ub) )
14258  {
14259  /* maybe unbounded */
14260  tryfixing = FALSE;
14261  break;
14262  }
14263 
14264  maxcondactivity += val * ub;
14265  mincondactivity += val * ub;
14266  }
14267  }
14268  else
14269  {
14270  /* consider contribution of discrete variables, non-singleton
14271  * continuous variables and variables with more than one lock
14272  */
14273  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14274  {
14275  tryfixing = FALSE;
14276  break;
14277  }
14278 
14279  if( val > 0 )
14280  {
14281  maxcondactivity += val * ub;
14282  mincondactivity += val * lb;
14283  }
14284  else
14285  {
14286  maxcondactivity += val * lb;
14287  mincondactivity += val * ub;
14288  }
14289  }
14290  }
14291  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14292  {
14293  SCIP_Real delta;
14294  SCIP_Bool tightened;
14295 #ifdef SCIP_DEBUG
14296  int oldnfixedvars = *nfixedvars;
14297  int oldnchgbds = *nchgbds;
14298 #endif
14299 
14300  SCIPsortRealInt(ratios, varpos, nsingletons);
14301 
14302  /* verify which singleton continuous variables can be fixed */
14303  for( v = 0; v < nsingletons; ++v )
14304  {
14305  idx = varpos[v];
14306  var = vars[idx];
14307  val = factor * vals[idx];
14308  lb = SCIPvarGetLbGlobal(var);
14309  ub = SCIPvarGetUbGlobal(var);
14310 
14311  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14312  assert((val < 0) == swapped[idx]);
14313  val = REALABS(val);
14314 
14315  /* stop fixing if variable bounds are not finite */
14316  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14317  break;
14318 
14321  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14322 
14323  /* calculate the change in the row activities if this variable changes
14324  * its value from its worst to its best bound
14325  */
14326  if( swapped[idx] )
14327  delta = -(lb - ub) * val;
14328  else
14329  delta = (ub - lb) * val;
14330 
14331  assert(!SCIPisNegative(scip, delta));
14332 
14333  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14334  {
14335  if( swapped[idx] )
14336  {
14337  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14338  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14339  }
14340  else
14341  {
14342  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14343  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14344  }
14345 
14346  if( *cutoff )
14347  break;
14348  if( tightened )
14349  {
14350  (*nfixedvars)++;
14351  }
14352  }
14353  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14354  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14355  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14356  * troubles in case of large bounds.
14357  */
14358  else if( SCIPisLE(scip, rhs, mincondactivity) )
14359  {
14360  if( swapped[idx] )
14361  {
14362  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14363  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14364  }
14365  else
14366  {
14367  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14368  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14369  }
14370 
14371  if( *cutoff )
14372  break;
14373  if( tightened )
14374  {
14375  (*nfixedvars)++;
14376  }
14377  }
14378 
14379  maxcondactivity += delta;
14380  mincondactivity += delta;
14381  }
14382 
14383 #ifdef SCIP_DEBUG
14384  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14385  {
14386  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14387  }
14388 #endif
14389  }
14390 
14391  SCIPfreeBufferArray(scip, &swapped);
14392  SCIPfreeBufferArray(scip, &ratios);
14393  SCIPfreeBufferArray(scip, &varpos);
14394  }
14395 
14396  /* perform single-variable stuffing:
14397  * for a linear inequality
14398  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14399  * with a_i > 0 and objective coefficients c_i < 0,
14400  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14401  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14402  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14403  * is redundant.
14404  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14405  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14406  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14407  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14408  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14409  * upper bound.
14410  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14411  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14412  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14413  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14414  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14415  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14416  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14417  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14418  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14419  * c_k * ceil((maxactivity - rhs)/val) is still better than
14420  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14421  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14422  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14423  * sign of coefficients in constraint and objective prevent the use of this method.
14424  */
14425  if( singlevarstuffing && !ismaxsettoinfinity )
14426  {
14427  SCIP_Real bestratio = -SCIPinfinity(scip);
14428  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14429  SCIP_Real ratio;
14430  int bestindex = -1;
14431  int bestuplocks = 0;
14432  int bestdownlocks = 1;
14433  int downlocks;
14434  int uplocks;
14435  SCIPdebug( int oldnfixedvars = *nfixedvars; )
14436  SCIPdebug( int oldnchgbds = *nchgbds; )
14437 
14438  /* loop over all variables to identify the best and second-best ratio */
14439  for( v = 0; v < nvars; ++v )
14440  {
14441  var = vars[v];
14442  obj = SCIPvarGetObj(var);
14443  val = factor * vals[v];
14444 
14445  assert(!SCIPisZero(scip, val));
14446 
14447  ratio = obj / val;
14448 
14449  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14450  if( !SCIPisNegative(scip, ratio) )
14451  {
14452  bestindex = -1;
14453  break;
14454  }
14455 
14456  if( val > 0 )
14457  {
14460  }
14461  else
14462  {
14463  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14465  }
14466 
14467  /* better ratio, update best candidate
14468  * @todo use some tolerance
14469  * @todo check size of domain and updated ratio for integer variables already?
14470  */
14471  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14472  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14473  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14474  {
14475  /* best index becomes second-best*/
14476  if( bestindex != -1 )
14477  {
14478  /* second-best index must not have more than 1 uplock */
14479  if( bestuplocks > 1 )
14480  {
14481  bestindex = -1;
14482  break;
14483  }
14484  else
14485  {
14486  secondbestratio = bestratio;
14487  }
14488  }
14489  bestdownlocks = downlocks;
14490  bestuplocks = uplocks;
14491  bestratio = ratio;
14492  bestindex = v;
14493 
14494  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14495  * if it is not the best, it has too many uplocks -> not applicable
14496  */
14497  if( bestdownlocks > 0 && bestuplocks > 1 )
14498  {
14499  bestindex = -1;
14500  break;
14501  }
14502  }
14503  else
14504  {
14505  /* non-best index must not have more than 1 uplock */
14506  if( uplocks > 1 )
14507  {
14508  bestindex = -1;
14509  break;
14510  }
14511  /* update second-best ratio */
14512  if( ratio > secondbestratio )
14513  {
14514  secondbestratio = ratio;
14515  }
14516  }
14517  }
14518 
14519  /* check if we can apply single variable stuffing */
14520  if( bestindex != -1 && bestdownlocks == 0 )
14521  {
14522  SCIP_Bool tightened = FALSE;
14523  SCIP_Real bounddelta;
14524 
14525  var = vars[bestindex];
14526  obj = SCIPvarGetObj(var);
14527  val = factor * vals[bestindex];
14528  lb = SCIPvarGetLbGlobal(var);
14529  ub = SCIPvarGetUbGlobal(var);
14530  tryfixing = TRUE;
14531 
14532  if( val < 0 )
14533  {
14534  assert(!SCIPisNegative(scip, obj));
14535 
14536  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14537  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14538  {
14539  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14540  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14541  assert(SCIPisPositive(scip, activitydelta));
14542 
14543  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14544 
14545  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14546  assert(SCIPisPositive(scip, bounddelta));
14547  }
14548  else
14549  bounddelta = (maxactivity - rhs)/-val;
14550 
14551  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14552 
14553  if( tryfixing )
14554  {
14555  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14556 
14557  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14558  {
14559  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14560  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14561  }
14562  else
14563  {
14564  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14565  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14566  }
14567  }
14568  }
14569  else
14570  {
14571  assert(!SCIPisPositive(scip, obj));
14572 
14573  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14574  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14575  {
14576  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14577  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14578  assert(SCIPisPositive(scip, activitydelta));
14579 
14580  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14581 
14582  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14583  assert(SCIPisPositive(scip, bounddelta));
14584  }
14585  else
14586  bounddelta = (maxactivity - rhs)/val;
14587 
14588  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14589 
14590  if( tryfixing )
14591  {
14592  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14593 
14594  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14595  {
14596  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14597  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14598  }
14599  else
14600  {
14601  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14602  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14603  }
14604  }
14605  }
14606 
14607  if( *cutoff )
14608  return SCIP_OKAY;
14609  if( tightened )
14610  {
14611  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14612  ++(*nfixedvars);
14613  else
14614  ++(*nchgbds);
14615 
14616  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14617  for( v = 0; v < nvars; ++v )
14618  {
14619  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14620  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14623  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14624  }
14625  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14626 
14627  for( v = 0; v < nvars; ++v )
14628  {
14629  if( v == bestindex )
14630  continue;
14631 
14632  if( factor * vals[v] < 0 )
14633  {
14634  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14635  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14636  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14637  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14638  }
14639  else
14640  {
14641  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14642  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14643  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14644  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14645  }
14646 
14647  if( *cutoff )
14648  return SCIP_OKAY;
14649  if( tightened )
14650  ++(*nfixedvars);
14651  }
14652  SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14653  }
14654  }
14655  }
14656 
14657  return SCIP_OKAY;
14658 }
14659 
14660 /** applies full dual presolving on variables that only appear in linear constraints */
14661 static
14663  SCIP* scip, /**< SCIP data structure */
14664  SCIP_CONS** conss, /**< constraint set */
14665  int nconss, /**< number of constraints */
14666  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14667  int* nchgbds /**< pointer to count the number of bound changes */
14668  )
14669 {
14670  SCIP_Real* redlb;
14671  SCIP_Real* redub;
14672  int* nlocksdown;
14673  int* nlocksup;
14674  SCIP_Bool* isimplint;
14675  SCIP_VAR** origvars;
14676  SCIP_VAR** vars;
14677  SCIP_VAR** conscontvars;
14678  int nvars;
14679  int nbinvars;
14680  int nintvars;
14681  int ncontvars;
14682  int v;
14683  int c;
14684 
14685  /* we calculate redundancy bounds with the following meaning:
14686  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14687  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14688  * then:
14689  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14690  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14691  */
14692 
14693  /* Additionally, we detect continuous variables that are implicitly integral.
14694  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14695  * and all constraints (including the bounds as trivial constraints) in which:
14696  * c_j > 0: the variable is down-locked,
14697  * c_j < 0: the variable is up-locked,
14698  * c_j = 0: the variable appears
14699  * have, apart from j, only integer variables with integral coefficients and integral sides.
14700  * This is because then, the value of the variable is either determined by one of its bounds or
14701  * by one of these constraints, and in all cases, the value of the variable is integral.
14702  */
14703 
14704  assert(scip != NULL);
14705  assert(nconss == 0 || conss != NULL);
14706  assert(nchgbds != NULL);
14707  assert(!SCIPinProbing(scip));
14708 
14709  /* get active variables */
14710  nvars = SCIPgetNVars(scip);
14711  origvars = SCIPgetVars(scip);
14712 
14713  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14714  nbinvars = SCIPgetNBinVars(scip);
14715  if( nbinvars == nvars )
14716  return SCIP_OKAY;
14717 
14718  /* get number of continuous variables */
14719  ncontvars = SCIPgetNContVars(scip);
14720  nintvars = nvars - ncontvars;
14721 
14722  /* copy the variable array since this array might change during the curse of this algorithm */
14723  nvars = nvars - nbinvars;
14724  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14725 
14726  /* allocate temporary memory */
14727  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14728  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14729  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14730  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14731  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14732  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14733 
14734  /* initialize redundancy bounds */
14735  for( v = 0; v < nvars; ++v )
14736  {
14737  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14738  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14739  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14740  }
14741  BMSclearMemoryArray(nlocksdown, nvars);
14742  BMSclearMemoryArray(nlocksup, nvars);
14743 
14744  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14745  * We better not use SCIPisFeasIntegral() in these checks.
14746  */
14747  for( v = 0; v < ncontvars; v++ )
14748  {
14749  SCIP_VAR* var;
14750  SCIP_Real obj;
14751  SCIP_Real lb;
14752  SCIP_Real ub;
14753 
14754  var = vars[v + nintvars - nbinvars];
14755  lb = SCIPvarGetLbGlobal(var);
14756  ub = SCIPvarGetUbGlobal(var);
14757 
14758  obj = SCIPvarGetObj(var);
14759  if( SCIPisZero(scip, obj) )
14760  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14761  else
14762  {
14763  if( SCIPisPositive(scip, obj) )
14764  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14765  else
14766  {
14767  assert(SCIPisNegative(scip, obj));
14768  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14769  }
14770  }
14771  }
14772 
14773  /* scan all constraints */
14774  for( c = 0; c < nconss; ++c )
14775  {
14776  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14777  * part of checked disjunctions)
14778  */
14779  if( SCIPconsIsLocked(conss[c]) )
14780  {
14781  SCIP_CONSDATA* consdata;
14782  SCIP_Bool lhsexists;
14783  SCIP_Bool rhsexists;
14784  SCIP_Bool hasimpliedpotential;
14785  SCIP_Bool integralcoefs;
14786  int nlockspos;
14787  int contvarpos;
14788  int nconscontvars;
14789  int i;
14790 
14791  consdata = SCIPconsGetData(conss[c]);
14792  assert(consdata != NULL);
14793 
14794  /* get number of times the constraint was locked */
14795  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14796 
14797  /* we do not want to include constraints with locked negation (this would be too weird) */
14798  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14799  {
14800  /* mark all continuous variables as not being implicit integral */
14801  for( i = 0; i < consdata->nvars; ++i )
14802  {
14803  SCIP_VAR* var;
14804 
14805  var = consdata->vars[i];
14807  {
14808  int contv;
14809  contv = SCIPvarGetProbindex(var) - nintvars;
14810  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14811  isimplint[contv] = FALSE;
14812  }
14813  }
14814  continue;
14815  }
14816 
14817  /* check for existing sides */
14818  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14819  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14820 
14821  /* count locks and update redundancy bounds */
14822  contvarpos = -1;
14823  nconscontvars = 0;
14824  hasimpliedpotential = FALSE;
14825  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14826 
14827  for( i = 0; i < consdata->nvars; ++i )
14828  {
14829  SCIP_VAR* var;
14830  SCIP_Real val;
14831  SCIP_Real minresactivity;
14832  SCIP_Real maxresactivity;
14833  SCIP_Real newredlb;
14834  SCIP_Real newredub;
14835  SCIP_Bool minisrelax;
14836  SCIP_Bool maxisrelax;
14837  SCIP_Bool isminsettoinfinity;
14838  SCIP_Bool ismaxsettoinfinity;
14839  int arrayindex;
14840 
14841  var = consdata->vars[i];
14842  val = consdata->vals[i];
14843 
14844  /* check if still all integer variables have integral coefficients */
14845  if( SCIPvarIsIntegral(var) )
14846  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14847 
14848  /* we do not need to process binary variables */
14849  if( SCIPvarIsBinary(var) )
14850  continue;
14851 
14852  if( SCIPconsIsModifiable(conss[c]) )
14853  {
14854  minresactivity = -SCIPinfinity(scip);
14855  maxresactivity = SCIPinfinity(scip);
14856  isminsettoinfinity = TRUE;
14857  ismaxsettoinfinity = TRUE;
14858  }
14859  else
14860  {
14861  /* calculate residual activity bounds if variable would be fixed to zero */
14862  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14863  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14864 
14865  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14866  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14867  * This is needed, because we do not want to rely on relaxed finite resactivities.
14868  */
14869  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14870 
14871  /* check minresactivity for reliability */
14872  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14873  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14874 
14875  /* check maxresactivity for reliability */
14876  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14877  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14878  }
14879 
14880  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14881 
14882  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14883 
14884  newredlb = redlb[arrayindex];
14885  newredub = redub[arrayindex];
14886  if( val > 0.0 )
14887  {
14888  if( lhsexists )
14889  {
14890  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14891  nlocksdown[arrayindex] += nlockspos;
14892  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14893  }
14894  if( rhsexists )
14895  {
14896  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14897  nlocksup[arrayindex] += nlockspos;
14898  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14899  }
14900  }
14901  else
14902  {
14903  if( lhsexists )
14904  {
14905  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14906  nlocksup[arrayindex] += nlockspos;
14907  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14908  }
14909  if( rhsexists )
14910  {
14911  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14912  nlocksdown[arrayindex] += nlockspos;
14913  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14914  }
14915  }
14916 
14917  /* if the variable is integer, we have to round the value to the next integral value */
14918  if( SCIPvarIsIntegral(var) )
14919  {
14920  if( !SCIPisInfinity(scip, newredlb) )
14921  newredlb = SCIPceil(scip, newredlb);
14922  if( !SCIPisInfinity(scip, -newredub) )
14923  newredub = SCIPfloor(scip, newredub);
14924  }
14925 
14926  /* update redundancy bounds */
14927  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14928  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14929 
14930  /* collect the continuous variables of the constraint */
14932  {
14933  int contv;
14934 
14935  assert(nconscontvars < ncontvars);
14936  contvarpos = i;
14937  conscontvars[nconscontvars] = var;
14938  nconscontvars++;
14939 
14940  contv = SCIPvarGetProbindex(var) - nintvars;
14941  assert(0 <= contv && contv < ncontvars);
14942  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14943  }
14944  }
14945 
14946  /* update implied integer status of continuous variables */
14947  if( hasimpliedpotential )
14948  {
14949  if( nconscontvars > 1 || !integralcoefs )
14950  {
14951  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14952  * none of the continuous variables is implied integer
14953  */
14954  for( i = 0; i < nconscontvars; i++ )
14955  {
14956  int contv;
14957  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14958  assert(0 <= contv && contv < ncontvars);
14959  isimplint[contv] = FALSE;
14960  }
14961  }
14962  else
14963  {
14964  SCIP_VAR* var;
14965  SCIP_Real val;
14966  SCIP_Real absval;
14967  int contv;
14968 
14969  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14970  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14971  * side(s) of the constraint is integral
14972  */
14973  assert(nconscontvars == 1);
14974  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14975  var = consdata->vars[contvarpos];
14976  val = consdata->vals[contvarpos];
14977  contv = SCIPvarGetProbindex(var) - nintvars;
14978  assert(0 <= contv && contv < ncontvars);
14979  assert(isimplint[contv]);
14980 
14981  absval = REALABS(val);
14982  if( !SCIPisEQ(scip, absval, 1.0) )
14983  isimplint[contv] = FALSE;
14984  else
14985  {
14986  SCIP_Real obj;
14987 
14988  obj = SCIPvarGetObj(var);
14989  if( obj * val >= 0.0 && lhsexists )
14990  {
14991  /* the variable may be blocked by the constraint's left hand side */
14992  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14993  }
14994  if( obj * val <= 0.0 && rhsexists )
14995  {
14996  /* the variable may be blocked by the constraint's left hand side */
14997  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14998  }
14999  }
15000  }
15001  }
15002  }
15003  }
15004 
15005  /* check if any bounds can be tightened due to optimality */
15006  for( v = 0; v < nvars; ++v )
15007  {
15008  SCIP_VAR* var;
15009  SCIP_Real obj;
15010  SCIP_Bool infeasible;
15011  SCIP_Bool tightened;
15012 
15013  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
15014  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15015  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15016 
15017  var = vars[v];
15018  obj = SCIPvarGetObj(var);
15019  if( obj >= 0.0 )
15020  {
15021  /* making the variable as small as possible does not increase the objective:
15022  * check if all down locks of the variables are due to linear constraints;
15023  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
15024  */
15025  if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15026  && !SCIPisInfinity(scip, -redlb[v])
15027  && redlb[v] < SCIPvarGetUbGlobal(var) )
15028  {
15029  SCIP_Real ub;
15030 
15031  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15032  * -> tighten upper bound to x_v <= redlb[v]
15033  */
15034  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15036  redlb[v]);
15037  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15038  assert(!infeasible);
15039 
15040  ub = SCIPvarGetUbGlobal(var);
15041  redub[v] = MIN(redub[v], ub);
15042  if( tightened )
15043  (*nchgbds)++;
15044  }
15045  }
15046  if( obj <= 0.0 )
15047  {
15048  /* making the variable as large as possible does not increase the objective:
15049  * check if all up locks of the variables are due to linear constraints;
15050  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
15051  */
15052  if( SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15053  && !SCIPisInfinity(scip, redub[v])
15054  && redub[v] > SCIPvarGetLbGlobal(var) )
15055  {
15056  SCIP_Real lb;
15057 
15058  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15059  * -> tighten lower bound to x_v >= redub[v]
15060  */
15061  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15063  redub[v]);
15064  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15065  assert(!infeasible);
15066 
15067  lb = SCIPvarGetLbGlobal(var);
15068  redlb[v] = MAX(redlb[v], lb);
15069  if( tightened )
15070  (*nchgbds)++;
15071  }
15072  }
15073  }
15074 
15075  /* upgrade continuous variables to implied integers */
15076  for( v = nintvars - nbinvars; v < nvars; ++v )
15077  {
15078  SCIP_VAR* var;
15079  SCIP_Bool infeasible;
15080 
15081  var = vars[v];
15082  assert(var != NULL);
15083 
15084  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
15085  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15086  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15087  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15088 
15089  /* we can only conclude implied integrality if the variable appears in no other constraint */
15090  if( isimplint[v - nintvars + nbinvars]
15091  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15092  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15093  {
15094  /* since we locally copied the variable array we can change the variable type immediately */
15095  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15096 
15097  if( infeasible )
15098  {
15099  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15100  *cutoff = TRUE;
15101 
15102  break;
15103  }
15104 
15105  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15107  }
15108  }
15109 
15110  /* free temporary memory */
15111  SCIPfreeBufferArray(scip, &conscontvars);
15112  SCIPfreeBufferArray(scip, &isimplint);
15113  SCIPfreeBufferArray(scip, &nlocksup);
15114  SCIPfreeBufferArray(scip, &nlocksdown);
15115  SCIPfreeBufferArray(scip, &redub);
15116  SCIPfreeBufferArray(scip, &redlb);
15117 
15118  SCIPfreeBufferArray(scip, &vars);
15119 
15120  return SCIP_OKAY;
15121 }
15122 
15123 /** helper function to enforce constraints */
15124 static
15126  SCIP* scip, /**< SCIP data structure */
15127  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15128  SCIP_CONS** conss, /**< constraints to process */
15129  int nconss, /**< number of constraints */
15130  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15131  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15132  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15133  )
15134 {
15135  SCIP_CONSHDLRDATA* conshdlrdata;
15136  SCIP_Bool checkrelmaxabs;
15137  SCIP_Bool violated;
15138  SCIP_Bool cutoff = FALSE;
15139  int c;
15140 
15141  assert(scip != NULL);
15142  assert(conshdlr != NULL);
15143  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15144  assert(result != NULL);
15145 
15146  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15147  assert(conshdlrdata != NULL);
15148 
15149  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15150 
15151  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15152 
15153  /* check for violated constraints
15154  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15155  */
15156  *result = SCIP_FEASIBLE;
15157 
15158  /* check all useful linear constraints for feasibility */
15159  for( c = 0; c < nusefulconss; ++c )
15160  {
15161  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15162 
15163  if( violated )
15164  {
15165  /* insert LP row as cut */
15166  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15167  if ( cutoff )
15168  *result = SCIP_CUTOFF;
15169  else
15170  *result = SCIP_SEPARATED;
15171  }
15172  }
15173 
15174  /* check all obsolete linear constraints for feasibility */
15175  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15176  {
15177  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15178 
15179  if( violated )
15180  {
15181  /* insert LP row as cut */
15182  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15183  if ( cutoff )
15184  *result = SCIP_CUTOFF;
15185  else
15186  *result = SCIP_SEPARATED;
15187  }
15188  }
15189 
15190  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15191 
15192  return SCIP_OKAY;
15193 }
15194 
15195 /*
15196  * Callback methods of constraint handler
15197  */
15198 
15199 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15200 static
15201 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15202 { /*lint --e{715}*/
15203  assert(scip != NULL);
15204  assert(conshdlr != NULL);
15205  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15206 
15207  /* call inclusion method of constraint handler */
15209 
15210  *valid = TRUE;
15211 
15212  return SCIP_OKAY;
15213 }
15214 
15215 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15216 static
15217 SCIP_DECL_CONSFREE(consFreeLinear)
15218 { /*lint --e{715}*/
15219  SCIP_CONSHDLRDATA* conshdlrdata;
15221  assert(scip != NULL);
15222  assert(conshdlr != NULL);
15223  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15224 
15225  /* free constraint handler data */
15226  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15227  assert(conshdlrdata != NULL);
15228 
15229  conshdlrdataFree(scip, &conshdlrdata);
15230 
15231  SCIPconshdlrSetData(conshdlr, NULL);
15232 
15233  return SCIP_OKAY;
15234 }
15235 
15237 /** initialization method of constraint handler (called after problem was transformed) */
15238 static
15239 SCIP_DECL_CONSINIT(consInitLinear)
15240 {
15241  SCIP_CONSHDLRDATA* conshdlrdata;
15242  int c;
15243 
15244  assert(scip != NULL);
15245 
15246  /* check for event handler */
15247  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15248  assert(conshdlrdata != NULL);
15249  assert(conshdlrdata->eventhdlr != NULL);
15250  assert(nconss == 0 || conss != NULL);
15251 
15252  conshdlrdata->naddconss = 0;
15253 
15254  /* catch events for the constraints */
15255  for( c = 0; c < nconss; ++c )
15256  {
15257  /* catch all events */
15258  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15259  }
15260 
15261  return SCIP_OKAY;
15262 }
15263 
15264 
15265 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15266 static
15267 SCIP_DECL_CONSEXIT(consExitLinear)
15268 {
15269  SCIP_CONSHDLRDATA* conshdlrdata;
15270  int c;
15271 
15272  assert(scip != NULL);
15273 
15274  /* check for event handler */
15275  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15276  assert(conshdlrdata != NULL);
15277  assert(conshdlrdata->eventhdlr != NULL);
15278 
15279  /* drop events for the constraints */
15280  for( c = nconss - 1; c >= 0; --c )
15281  {
15282  SCIP_CONSDATA* consdata;
15283 
15284  consdata = SCIPconsGetData(conss[c]);
15285  assert(consdata != NULL);
15287  if( consdata->eventdata != NULL )
15288  {
15289  /* drop all events */
15290  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15291  assert(consdata->eventdata == NULL);
15292  }
15293  }
15294 
15295  return SCIP_OKAY;
15296 }
15297 
15298 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15299 static
15301  SCIP* scip, /**< SCIP data structure */
15302  SCIP_Real lhs, /**< left hand side */
15303  SCIP_Real rhs /**< right hand side */
15304  )
15305 {
15306  assert(scip != NULL);
15307 
15308  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15309 }
15310 
15311 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15312 static
15314  SCIP* scip, /**< SCIP data structure */
15315  SCIP_Real x /**< value */
15316  )
15317 {
15318  assert(scip != NULL);
15320  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15321 }
15322 
15323 /** performs linear constraint type classification as used for MIPLIB
15324  *
15325  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15326  *
15327  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15328  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15329  * Similarly, if specialized constraints were created through the API, these are currently not present.
15330  */
15332  SCIP* scip, /**< SCIP data structure */
15333  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15334  )
15335 {
15336  int c;
15337  SCIP_CONSHDLR* conshdlr;
15338  SCIP_CONS** conss;
15339  int nconss;
15340 
15341  assert(scip != NULL);
15342  assert(linconsstats != NULL);
15343  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15344  assert(conshdlr != NULL);
15345 
15346  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15347  {
15348  conss = SCIPgetConss(scip);
15349  nconss = SCIPgetNConss(scip);
15350  }
15351  else
15352  {
15353  conss = SCIPconshdlrGetConss(conshdlr);
15354  nconss = SCIPconshdlrGetNConss(conshdlr);
15355  }
15356 
15357  /* reset linear constraint type classification */
15358  SCIPlinConsStatsReset(linconsstats);
15359 
15360  /* loop through all constraints */
15361  for( c = 0; c < nconss; c++ )
15362  {
15363  SCIP_CONS* cons;
15364  SCIP_CONSDATA* consdata;
15365  SCIP_Real lhs;
15366  SCIP_Real rhs;
15367  int i;
15368 
15369  /* get constraint */
15370  cons = conss[c];
15371  assert(cons != NULL);
15372 
15373  /* skip constraints that are not handled by the constraint handler */
15374  if( SCIPconsGetHdlr(cons) != conshdlr )
15375  continue;
15376 
15377  /* get constraint data */
15378  consdata = SCIPconsGetData(cons);
15379  assert(consdata != NULL);
15380  rhs = consdata->rhs;
15381  lhs = consdata->lhs;
15382 
15383  /* merge multiples and delete variables with zero coefficient */
15384  SCIP_CALL( mergeMultiples(scip, cons) );
15385  for( i = 0; i < consdata->nvars; i++ )
15386  {
15387  assert(!SCIPisZero(scip, consdata->vals[i]));
15388  }
15389 
15390  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15391  if( consdata->nvars == 0 )
15392  {
15393  SCIPdebugMsg(scip, "classified as EMPTY: ");
15394  SCIPdebugPrintCons(scip, cons, NULL);
15396 
15397  continue;
15398  }
15399 
15400  /* is constraint of type SCIP_CONSTYPE_FREE? */
15401  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15402  {
15403  SCIPdebugMsg(scip, "classified as FREE: ");
15404  SCIPdebugPrintCons(scip, cons, NULL);
15406 
15407  continue;
15408  }
15409 
15410  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15411  if( consdata->nvars == 1 )
15412  {
15413  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15414  SCIPdebugPrintCons(scip, cons, NULL);
15415  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15416 
15417  continue;
15418  }
15419 
15420  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15421  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15422  {
15423  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15424  SCIPdebugPrintCons(scip, cons, NULL);
15426 
15427  continue;
15428  }
15429 
15430  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15431  if( consdata->nvars == 2 )
15432  {
15433  SCIP_LINCONSTYPE constype;
15434 
15435  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15436  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15437  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15438  {
15439  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15440  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15441  }
15442  else
15443  {
15444  constype = SCIP_LINCONSTYPE_VARBOUND;
15445  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15446  }
15447  SCIPdebugPrintCons(scip, cons, NULL);
15448 
15449  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15450 
15451  continue;
15452  }
15453 
15454  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15455  {
15456  SCIP_Real scale;
15457  SCIP_Real b;
15458  SCIP_Bool unmatched;
15459  int nnegbinvars;
15460 
15461  unmatched = FALSE;
15462  nnegbinvars = 0;
15463 
15464  scale = REALABS(consdata->vals[0]);
15465 
15466  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15467  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15468  {
15469  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15470  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15471  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15472  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15473 
15474  if( consdata->vals[i] < 0.0 )
15475  nnegbinvars++;
15476  }
15477 
15478  if( !unmatched )
15479  {
15480  if( SCIPisEQ(scip, lhs, rhs) )
15481  {
15482  b = rhs/scale + nnegbinvars;
15483  if( SCIPisEQ(scip, 1.0, b) )
15484  {
15485  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15486  SCIPdebugPrintCons(scip, cons, NULL);
15488 
15489  continue;
15490  }
15491  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15492  {
15493  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15494  SCIPdebugPrintCons(scip, cons, NULL);
15496 
15497  continue;
15498  }
15499  }
15500 
15501  /* compute right hand side divided by scale */
15502  if( !SCIPisInfinity(scip, rhs) )
15503  b = rhs/scale + nnegbinvars;
15504  else
15505  b = SCIPinfinity(scip);
15506 
15507  if( SCIPisEQ(scip, 1.0, b) )
15508  {
15509  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15510  SCIPdebugPrintCons(scip, cons, NULL);
15512 
15513  /* relax right hand side to prevent further classifications */
15514  rhs = SCIPinfinity(scip);
15515  }
15516  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15517  {
15518  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15519  SCIPdebugPrintCons(scip, cons, NULL);
15520 
15522 
15523  /* relax right hand side to prevent further classifications */
15524  rhs = SCIPinfinity(scip);
15525  }
15526 
15527  if( !SCIPisInfinity(scip, lhs) )
15528  b = lhs/scale + nnegbinvars;
15529  else
15530  b = SCIPinfinity(scip);
15531 
15532  if( SCIPisEQ(scip, 1.0, b) )
15533  {
15534  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15535  SCIPdebugPrintCons(scip, cons, NULL);
15537 
15538  /* relax left hand side to prevent further classifications */
15539  lhs = -SCIPinfinity(scip);
15540  }
15541 
15542  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15543  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15544  continue;
15545  }
15546  }
15547 
15548  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15549  /* @todo If coefficients or rhs are not integral, we currently do not check
15550  * if the constraint could be scaled (finitely), such that they are.
15551  */
15552  {
15553  SCIP_Real b;
15554  SCIP_Bool unmatched;
15555 
15556  b = rhs;
15557  unmatched = FALSE;
15558  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15559  {
15560  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15561  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15562  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15563  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15564 
15565  if( SCIPisNegative(scip, consdata->vals[i]) )
15566  b -= consdata->vals[i];
15567  }
15568  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15569 
15570  if( !unmatched )
15571  {
15572  if( SCIPisEQ(scip, lhs, rhs) )
15573  {
15574  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15575  SCIPdebugPrintCons(scip, cons, NULL);
15576 
15578 
15579  continue;
15580  }
15581  else
15582  {
15583  SCIP_Bool matched;
15584 
15585  matched = FALSE;
15586  for( i = 0; i < consdata->nvars && !matched; i++ )
15587  {
15588  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15589  }
15590 
15591  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15592  SCIPdebugPrintCons(scip, cons, NULL);
15594  }
15595 
15596  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15597  if( SCIPisInfinity(scip, -lhs) )
15598  continue;
15599  else
15600  rhs = SCIPinfinity(scip);
15601  }
15602  }
15603 
15604  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15605  {
15606  SCIP_Real b;
15607  SCIP_Bool unmatched;
15608 
15609  unmatched = FALSE;
15610 
15611  b = rhs;
15612  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15613 
15614  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15615  {
15616  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15617  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15618  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15619  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15620  }
15621 
15622  if( !unmatched )
15623  {
15624  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15625  SCIPdebugPrintCons(scip, cons, NULL);
15627 
15628  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15629  if( SCIPisInfinity(scip, -lhs) )
15630  continue;
15631  else
15632  rhs = SCIPinfinity(scip);
15633  }
15634  }
15635 
15636  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15637  {
15638  SCIP_Bool unmatched;
15639 
15640  unmatched = FALSE;
15641  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15642  {
15643  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15644  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15645  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15646  unmatched = TRUE;
15647  }
15648 
15649  if( !unmatched )
15650  {
15651  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15652  SCIPdebugPrintCons(scip, cons, NULL);
15653  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15654 
15655  continue;
15656  }
15657  }
15658 
15659  /* no special structure detected */
15660  SCIPdebugMsg(scip, "classified as GENERAL: ");
15661  SCIPdebugPrintCons(scip, cons, NULL);
15662  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15663  }
15664 
15665  return SCIP_OKAY;
15666 }
15667 
15668 
15669 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15670 static
15671 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15672 { /*lint --e{715}*/
15673  int c;
15674 #ifdef SCIP_STATISTIC
15675  SCIP_CONSHDLRDATA* conshdlrdata;
15676  int ngoodconss;
15677  int nallconss;
15678 #endif
15679 
15680  /* delete all linear constraints that were upgraded to a more specific constraint type;
15681  * make sure, only active variables remain in the remaining constraints
15682  */
15683  assert(scip != NULL);
15684 
15685 #ifdef SCIP_STATISTIC
15686  /* count number of well behaved linear constraints */
15687  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15688  assert(conshdlrdata != NULL);
15689 
15690  ngoodconss = 0;
15691  nallconss = 0;
15692 
15693  for( c = 0; c < nconss; ++c )
15694  {
15695  SCIP_CONSDATA* consdata;
15696 
15697  if( SCIPconsIsDeleted(conss[c]) )
15698  continue;
15699 
15700  consdata = SCIPconsGetData(conss[c]);
15701  assert(consdata != NULL);
15702 
15703  if( consdata->upgraded )
15704  continue;
15705 
15706  nallconss++;
15707 
15708  consdataRecomputeMaxActivityDelta(scip, consdata);
15709 
15710  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15711  ngoodconss++;
15712  }
15713  if( nallconss )
15714  {
15715  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15716  }
15717 #endif
15718 
15719  for( c = 0; c < nconss; ++c )
15720  {
15721  SCIP_CONSDATA* consdata;
15722 
15723  if( SCIPconsIsDeleted(conss[c]) )
15724  continue;
15725 
15726  consdata = SCIPconsGetData(conss[c]);
15727  assert(consdata != NULL);
15728 
15729  if( consdata->upgraded )
15730  {
15731  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15732  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15733  */
15734  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15735  }
15736  else
15737  {
15738  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15739  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15740  }
15741  }
15742 
15743  return SCIP_OKAY;
15744 }
15745 
15746 /** solving process initialization method of constraint handler */
15747 static
15748 SCIP_DECL_CONSINITSOL(consInitsolLinear)
15749 { /*lint --e{715}*/
15750 
15751  /* add nlrow representation to NLP, if NLP had been constructed */
15752  if( SCIPisNLPConstructed(scip) )
15753  {
15754  int c;
15755  for( c = 0; c < nconss; ++c )
15756  {
15757  SCIP_CALL( addNlrow(scip, conss[c]) );
15758  }
15759  }
15760 
15761  return SCIP_OKAY;
15762 }
15763 
15764 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15765 static
15766 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15767 { /*lint --e{715}*/
15768  int c;
15769 
15770  assert(scip != NULL);
15771 
15772  /* release the rows and nlrows of all constraints */
15773  for( c = 0; c < nconss; ++c )
15774  {
15775  SCIP_CONSDATA* consdata;
15776 
15777  consdata = SCIPconsGetData(conss[c]);
15778  assert(consdata != NULL);
15779 
15780  if( consdata->row != NULL )
15781  {
15782  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15783  }
15784 
15785  if( consdata->nlrow != NULL )
15786  {
15787  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15788  }
15789  }
15790 
15791  /* if this is a restart, convert cutpool rows into linear constraints */
15792  if( restart )
15793  {
15794  int ncutsadded;
15795 
15796  ncutsadded = 0;
15797 
15798  /* create out of all active cuts in cutpool linear constraints */
15799  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15800 
15801  if( ncutsadded > 0 )
15802  {
15804  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15805  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15806  * line correctly
15807  */
15809  }
15810  }
15811 
15812  return SCIP_OKAY;
15813 }
15814 
15815 
15816 /** constraint activation notification method of constraint handler */
15817 static
15818 SCIP_DECL_CONSACTIVE(consActiveLinear)
15819 { /*lint --e{715}*/
15820  assert(cons != NULL);
15821 
15822  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
15823  {
15824  SCIP_CALL( addNlrow(scip, cons) );
15825  }
15826 
15827  return SCIP_OKAY;
15828 }
15829 
15830 /** constraint deactivation notification method of constraint handler */
15831 static
15832 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15833 { /*lint --e{715}*/
15834  SCIP_CONSDATA* consdata;
15835 
15836  assert(scip != NULL);
15837  assert(conshdlr != NULL);
15838  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15839  assert(cons != NULL );
15840 
15841  /* get constraint data */
15842  consdata = SCIPconsGetData(cons);
15843  assert(consdata != NULL);
15844 
15845  if( SCIPconsIsDeleted(cons) )
15846  {
15847  SCIP_CONSHDLRDATA* conshdlrdata;
15848 
15849  /* check for event handler */
15850  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15851  assert(conshdlrdata != NULL);
15852  assert(conshdlrdata->eventhdlr != NULL);
15853 
15854  /* free event data */
15855  if( consdata->eventdata != NULL )
15856  {
15857  /* drop bound change events of variables */
15858  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15859  }
15860  assert(consdata->eventdata == NULL);
15861  }
15862 
15863  /* remove row from NLP, if still in solving
15864  * if we are in exitsolve, the whole NLP will be freed anyway
15865  */
15866  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15867  {
15868  SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15869  }
15870 
15871  return SCIP_OKAY;
15872 }
15873 
15874 
15875 /** frees specific constraint data */
15876 static
15877 SCIP_DECL_CONSDELETE(consDeleteLinear)
15878 { /*lint --e{715}*/
15879  assert(scip != NULL);
15880  assert(conshdlr != NULL);
15881  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15882 
15883  if( (*consdata)->eventdata != NULL )
15884  {
15885  SCIP_CONSHDLRDATA* conshdlrdata;
15886 
15887  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15888  assert(conshdlrdata != NULL);
15889 
15890  /* drop all events */
15891  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15892  assert((*consdata)->eventdata == NULL);
15893  }
15894 
15895  /* free linear constraint */
15896  SCIP_CALL( consdataFree(scip, consdata) );
15897 
15898  return SCIP_OKAY;
15899 }
15900 
15901 
15902 /** transforms constraint data into data belonging to the transformed problem */
15903 static
15904 SCIP_DECL_CONSTRANS(consTransLinear)
15905 { /*lint --e{715}*/
15906  SCIP_CONSDATA* sourcedata;
15907  SCIP_CONSDATA* targetdata;
15908 
15909  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15910 
15911  assert(scip != NULL);
15912  assert(conshdlr != NULL);
15913  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15914  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15915  assert(sourcecons != NULL);
15916  assert(targetcons != NULL);
15917 
15918  sourcedata = SCIPconsGetData(sourcecons);
15919  assert(sourcedata != NULL);
15920  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15921 
15922  /* create linear constraint data for target constraint */
15923  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15924 
15925 #ifndef NDEBUG
15926  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15927  if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15928  {
15929  int n;
15930  for(n = targetdata->nvars - 1; n >= 0; --n )
15931  assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15932  }
15933 #endif
15934 
15935  /* create target constraint */
15936  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15937  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15938  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15939  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15940  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15941 
15942  return SCIP_OKAY;
15943 }
15944 
15945 
15946 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15947 static
15948 SCIP_DECL_CONSINITLP(consInitlpLinear)
15949 { /*lint --e{715}*/
15950  int c;
15951 
15952  assert(scip != NULL);
15953  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15954 
15955  *infeasible = FALSE;
15956 
15957  for( c = 0; c < nconss && !(*infeasible); ++c )
15958  {
15959  assert(SCIPconsIsInitial(conss[c]));
15960  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15961  }
15962 
15963  return SCIP_OKAY;
15964 }
15965 
15966 
15967 /** separation method of constraint handler for LP solutions */
15968 static
15969 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15970 { /*lint --e{715}*/
15971  SCIP_CONSHDLRDATA* conshdlrdata;
15972  SCIP_Real loclowerbound;
15973  SCIP_Real glblowerbound;
15974  SCIP_Real cutoffbound;
15975  SCIP_Real maxbound;
15976  SCIP_Bool separatecards;
15977  SCIP_Bool cutoff;
15978  int c;
15979  int depth;
15980  int nrounds;
15981  int maxsepacuts;
15982  int ncuts;
15983 
15984  assert(scip != NULL);
15985  assert(conshdlr != NULL);
15986  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15987  assert(result != NULL);
15989  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15990  assert(conshdlrdata != NULL);
15991  depth = SCIPgetDepth(scip);
15992  nrounds = SCIPgetNSepaRounds(scip);
15993 
15994  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15995 
15996  *result = SCIP_DIDNOTRUN;
15997 
15998  /* only call the separator a given number of times at each node */
15999  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16000  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16001  return SCIP_OKAY;
16002 
16003  /* get the maximal number of cuts allowed in a separation round */
16004  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16005 
16006  /* check if we want to produce knapsack cardinality cuts at this node */
16007  loclowerbound = SCIPgetLocalLowerbound(scip);
16008  glblowerbound = SCIPgetLowerbound(scip);
16009  cutoffbound = SCIPgetCutoffbound(scip);
16010  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16011  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16012  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16013 
16014  *result = SCIP_DIDNOTFIND;
16015  ncuts = 0;
16016  cutoff = FALSE;
16017 
16018  /* check all useful linear constraints for feasibility */
16019  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16020  {
16021  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16022  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16023  }
16024 
16025  /* adjust return value */
16026  if( cutoff )
16027  *result = SCIP_CUTOFF;
16028  else if( ncuts > 0 )
16029  *result = SCIP_SEPARATED;
16030 
16031  /* combine linear constraints to get more cuts */
16032  /**@todo further cuts of linear constraints */
16033 
16034  return SCIP_OKAY;
16035 }
16036 
16037 
16038 /** separation method of constraint handler for arbitrary primal solutions */
16039 static
16040 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16041 { /*lint --e{715}*/
16042  SCIP_CONSHDLRDATA* conshdlrdata;
16043  int c;
16044  int depth;
16045  int nrounds;
16046  int maxsepacuts;
16047  int ncuts;
16048  SCIP_Bool cutoff;
16049 
16050  assert(scip != NULL);
16051  assert(conshdlr != NULL);
16052  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16053  assert(result != NULL);
16054 
16055  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16056  assert(conshdlrdata != NULL);
16057  depth = SCIPgetDepth(scip);
16058  nrounds = SCIPgetNSepaRounds(scip);
16060  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16061 
16062  *result = SCIP_DIDNOTRUN;
16063 
16064  /* only call the separator a given number of times at each node */
16065  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16066  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16067  return SCIP_OKAY;
16068 
16069  /* get the maximal number of cuts allowed in a separation round */
16070  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16071 
16072  *result = SCIP_DIDNOTFIND;
16073  ncuts = 0;
16074  cutoff = FALSE;
16075 
16076  /* check all useful linear constraints for feasibility */
16077  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16078  {
16079  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16080  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16081  }
16082 
16083  /* adjust return value */
16084  if( cutoff )
16085  *result = SCIP_CUTOFF;
16086  else if( ncuts > 0 )
16087  *result = SCIP_SEPARATED;
16088 
16089  /* combine linear constraints to get more cuts */
16090  /**@todo further cuts of linear constraints */
16091 
16092  return SCIP_OKAY;
16093 }
16094 
16095 
16096 /** constraint enforcing method of constraint handler for LP solutions */
16097 static
16098 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16099 { /*lint --e{715}*/
16100  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16101 
16102  return SCIP_OKAY;
16103 }
16104 
16105 /** constraint enforcing method of constraint handler for relaxation solutions */
16106 static
16107 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16108 { /*lint --e{715}*/
16109  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16110 
16111  return SCIP_OKAY;
16112 }
16113 
16114 /** constraint enforcing method of constraint handler for pseudo solutions */
16115 static
16116 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16117 { /*lint --e{715}*/
16118  SCIP_CONSHDLRDATA* conshdlrdata;
16119  SCIP_Bool checkrelmaxabs;
16120  SCIP_Bool violated;
16121  int c;
16122 
16123  assert(scip != NULL);
16124  assert(conshdlr != NULL);
16125  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16126  assert(result != NULL);
16127 
16128  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16129  assert(conshdlrdata != NULL);
16130 
16131  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16132 
16133  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16134 
16135  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16136  if( objinfeasible )
16137  {
16138  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16139 
16140  *result = SCIP_DIDNOTRUN;
16141  return SCIP_OKAY;
16142  }
16143 
16144  /* check all linear constraints for feasibility */
16145  violated = FALSE;
16146  for( c = 0; c < nconss && !violated; ++c )
16147  {
16148  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16149  }
16150 
16151  if( violated )
16152  *result = SCIP_INFEASIBLE;
16153  else
16154  *result = SCIP_FEASIBLE;
16155 
16156  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16157 
16158  return SCIP_OKAY;
16159 }
16160 
16161 
16162 /** feasibility check method of constraint handler for integral solutions */
16163 static
16164 SCIP_DECL_CONSCHECK(consCheckLinear)
16165 { /*lint --e{715}*/
16166  SCIP_CONSHDLRDATA* conshdlrdata;
16167  SCIP_Bool checkrelmaxabs;
16168  int c;
16169 
16170  assert(scip != NULL);
16171  assert(conshdlr != NULL);
16172  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16173  assert(result != NULL);
16174 
16175  *result = SCIP_FEASIBLE;
16176 
16177  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16178  assert(conshdlrdata != NULL);
16179 
16180  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16181 
16182  /*debugMsg(scip, "Check method of linear constraints\n");*/
16184  /* check all linear constraints for feasibility */
16185  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16186  {
16187  SCIP_Bool violated = FALSE;
16188  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16189 
16190  if( violated )
16191  {
16192  *result = SCIP_INFEASIBLE;
16193 
16194  if( printreason )
16195  {
16196  SCIP_CONSDATA* consdata;
16197  SCIP_Real activity;
16198 
16199  consdata = SCIPconsGetData(conss[c]);
16200  assert( consdata != NULL);
16201 
16202  activity = consdataGetActivity(scip, consdata, sol);
16203 
16204  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16205  SCIPinfoMessage(scip, NULL, ";\n");
16206 
16207  if( activity == SCIP_INVALID ) /*lint !e777*/
16208  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16209  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16210  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16211  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16212  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16213  }
16214  }
16215  }
16216 
16217  return SCIP_OKAY;
16218 }
16219 
16220 
16221 /** domain propagation method of constraint handler */
16222 static
16223 SCIP_DECL_CONSPROP(consPropLinear)
16224 { /*lint --e{715}*/
16225  SCIP_CONSHDLRDATA* conshdlrdata;
16226  SCIP_Bool rangedrowpropagation = FALSE;
16227  SCIP_Bool tightenbounds;
16228  SCIP_Bool cutoff;
16229 
16230  int nchgbds;
16231  int i;
16232 
16233  assert(scip != NULL);
16234  assert(conshdlr != NULL);
16235  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16236  assert(result != NULL);
16237 
16238  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16239  assert(conshdlrdata != NULL);
16240 
16241  /*debugMsg(scip, "Prop method of linear constraints\n");*/
16243  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16244  if( SCIPinProbing(scip) )
16245  tightenbounds = TRUE;
16246  else
16247  {
16248  int depth;
16249  int propfreq;
16250  int tightenboundsfreq;
16251  int rangedrowfreq;
16252 
16253  depth = SCIPgetDepth(scip);
16254  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16255  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16256  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16257  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16258 
16259  /* check if we want to do ranged row propagation */
16260  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16261  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16262  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16263  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16264  rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16265  && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16266  }
16267 
16268  cutoff = FALSE;
16269  nchgbds = 0;
16270 
16271  /* process constraints marked for propagation */
16272  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16273  {
16274  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16275  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16276  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16277  }
16278 
16279  /* adjust result code */
16280  if( cutoff )
16281  *result = SCIP_CUTOFF;
16282  else if( nchgbds > 0 )
16283  *result = SCIP_REDUCEDDOM;
16284  else
16285  *result = SCIP_DIDNOTFIND;
16286 
16287  return SCIP_OKAY;
16288 }
16289 
16290 
16291 #define MAXCONSPRESOLROUNDS 10
16292 /** presolving method of constraint handler */
16293 static
16294 SCIP_DECL_CONSPRESOL(consPresolLinear)
16295 { /*lint --e{715}*/
16296  SCIP_CONSHDLRDATA* conshdlrdata;
16297  SCIP_CONS* cons;
16298  SCIP_CONSDATA* consdata;
16299  SCIP_Real minactivity;
16300  SCIP_Real maxactivity;
16301  SCIP_Bool minactisrelax;
16302  SCIP_Bool maxactisrelax;
16303  SCIP_Bool isminsettoinfinity;
16304  SCIP_Bool ismaxsettoinfinity;
16305  SCIP_Bool cutoff;
16306  int oldnfixedvars;
16307  int oldnaggrvars;
16308  int oldnchgbds;
16309  int oldndelconss;
16310  int oldnupgdconss;
16311  int oldnchgcoefs;
16312  int oldnchgsides;
16313  int firstchange;
16314  int firstupgradetry;
16315  int c;
16316 
16317  assert(scip != NULL);
16318  assert(conshdlr != NULL);
16319  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16320  assert(result != NULL);
16321 
16322  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16323 
16324  /* remember old preprocessing counters */
16325  cutoff = FALSE;
16326  oldnfixedvars = *nfixedvars;
16327  oldnaggrvars = *naggrvars;
16328  oldnchgbds = *nchgbds;
16329  oldndelconss = *ndelconss;
16330  oldnupgdconss = *nupgdconss;
16331  oldnchgcoefs = *nchgcoefs;
16332  oldnchgsides = *nchgsides;
16333 
16334  /* get constraint handler data */
16335  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16336  assert(conshdlrdata != NULL);
16337 
16338  /* process single constraints */
16339  firstchange = INT_MAX;
16340  firstupgradetry = INT_MAX;
16341  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16342  {
16343  int npresolrounds;
16344  SCIP_Bool infeasible;
16345 
16346  infeasible = FALSE;
16347 
16348  cons = conss[c];
16349  assert(SCIPconsIsActive(cons));
16350  consdata = SCIPconsGetData(cons);
16351  assert(consdata != NULL);
16352 
16353  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16354  if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16355  {
16356  consdata->lhs = consdata->rhs;
16357  assert(consdata->row == NULL);
16358  }
16359 
16360  if( consdata->eventdata == NULL )
16361  {
16362  /* catch bound change events of variables */
16363  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16364  assert(consdata->eventdata != NULL);
16365  }
16366 
16367  /* constraint should not be already presolved in the initial round */
16368  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16369  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16370  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16371  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16372 
16373  /* incorporate fixings and aggregations in constraint */
16374  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16375 
16376  if( infeasible )
16377  {
16378  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16379  cutoff = TRUE;
16380  break;
16381  }
16382 
16383  assert(consdata->removedfixings);
16384 
16385  /* we can only presolve linear constraints, that are not modifiable */
16386  if( SCIPconsIsModifiable(cons) )
16387  continue;
16388 
16389  /* remember the first changed constraint to begin the next aggregation round with */
16390  if( firstchange == INT_MAX && consdata->changed )
16391  firstchange = c;
16392 
16393  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16394  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16395  firstupgradetry = c;
16396 
16397  /* check, if constraint is already preprocessed */
16398  if( consdata->presolved )
16399  continue;
16400 
16401  assert(SCIPconsIsActive(cons));
16402 
16403  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16404  SCIPdebugPrintCons(scip, cons, NULL);
16405 
16406  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16407  * to avoid nearly infinite cycling due to very small bound changes)
16408  */
16409  npresolrounds = 0;
16410  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16411  {
16412  assert(!cutoff);
16413  npresolrounds++;
16414 
16415  /* mark constraint being presolved and propagated */
16416  consdata->presolved = TRUE;
16417  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16418 
16419  /* normalize constraint */
16420  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16421 
16422  if( infeasible )
16423  {
16424  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16425  cutoff = TRUE;
16426  break;
16427  }
16428 
16429  /* tighten left and right hand side due to integrality */
16430  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16431 
16432  if( infeasible )
16433  {
16434  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16435  cutoff = TRUE;
16436  break;
16437  }
16438 
16439  /* check bounds */
16440  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16441  {
16442  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16443  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16444  cutoff = TRUE;
16445  break;
16446  }
16447 
16448  /* tighten variable's bounds */
16449  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16450  if( cutoff )
16451  break;
16452 
16453  /* check for fixed variables */
16454  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16455  if( cutoff )
16456  break;
16457 
16458  /* check constraint for infeasibility and redundancy */
16459  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16460  &isminsettoinfinity, &ismaxsettoinfinity);
16461  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16462  {
16463  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16464  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16465  cutoff = TRUE;
16466  break;
16467  }
16468  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16469  {
16470  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16471  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16472  SCIP_CALL( SCIPdelCons(scip, cons) );
16473  assert(!SCIPconsIsActive(cons));
16474 
16475  if( !consdata->upgraded )
16476  (*ndelconss)++;
16477  break;
16478  }
16479  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16480  {
16481  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16482  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16483  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16484  if( !consdata->upgraded )
16485  (*nchgsides)++;
16486  }
16487  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16488  {
16489  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16490  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16491  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16492  if( !consdata->upgraded )
16493  (*nchgsides)++;
16494  }
16495 
16496  /* handle empty constraint */
16497  if( consdata->nvars == 0 )
16498  {
16499  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16500  {
16501  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16502  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16503  cutoff = TRUE;
16504  }
16505  else
16506  {
16507  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16508  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16509  SCIP_CALL( SCIPdelCons(scip, cons) );
16510  assert(!SCIPconsIsActive(cons));
16511 
16512  if( !consdata->upgraded )
16513  (*ndelconss)++;
16514  }
16515  break;
16516  }
16517 
16518  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16519  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16520 
16521  /* try to simplify inequalities */
16522  if( conshdlrdata->simplifyinequalities )
16523  {
16524  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16525 
16526  if( cutoff )
16527  break;
16528  }
16529 
16530  /* aggregation variable in equations */
16531  if( conshdlrdata->aggregatevariables )
16532  {
16533  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16534  if( cutoff )
16535  break;
16536  }
16537  }
16538 
16539  if( !cutoff && !SCIPisStopped(scip) )
16540  {
16541  /* perform ranged row propagation */
16542  if( conshdlrdata->rangedrowpropagation )
16543  {
16544  int lastnfixedvars;
16545 
16546  lastnfixedvars = *nfixedvars;
16547 
16548  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16549  if( !cutoff )
16550  {
16551  if( lastnfixedvars < *nfixedvars )
16552  {
16553  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16554  }
16555  }
16556  }
16557 
16558  /* extract cliques from constraint */
16559  if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16560  {
16561  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16562  nfixedvars, nchgbds, &cutoff) );
16563 
16564  /* check if the constraint got redundant or infeasible */
16565  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16566  {
16567  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16568  {
16569  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16570  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16571  cutoff = TRUE;
16572  }
16573  else
16574  {
16575  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16576  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16577  SCIP_CALL( SCIPdelCons(scip, cons) );
16578  assert(!SCIPconsIsActive(cons));
16579 
16580  if( !consdata->upgraded )
16581  (*ndelconss)++;
16582  }
16583  }
16584  }
16585 
16586  /* convert special equalities */
16587  if( !cutoff && SCIPconsIsActive(cons) )
16588  {
16589  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16590  }
16591 
16592  /* apply dual presolving for variables that appear in only one constraint */
16593  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16594  {
16595  SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16596  }
16597 
16598  /* check if an inequality is parallel to the objective function */
16599  if( !cutoff && SCIPconsIsActive(cons) )
16600  {
16601  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16602  }
16603 
16604  /* remember the first changed constraint to begin the next aggregation round with */
16605  if( firstchange == INT_MAX && consdata->changed )
16606  firstchange = c;
16607 
16608  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16609  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16610  firstupgradetry = c;
16611  }
16612 
16613  /* singleton column stuffing */
16614  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16615  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16616  {
16617  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16618  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16619 
16620  /* handle empty constraint */
16621  if( consdata->nvars == 0 )
16622  {
16623  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16624  {
16625  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16626  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16627  cutoff = TRUE;
16628  }
16629  else
16630  {
16631  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16632  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16633  SCIP_CALL( SCIPdelCons(scip, cons) );
16634  assert(!SCIPconsIsActive(cons));
16635 
16636  if( !consdata->upgraded )
16637  (*ndelconss)++;
16638  }
16639  break;
16640  }
16641  }
16642  }
16643 
16644  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16645  * only apply this expensive procedure in exhaustive presolving timing
16646  */
16647  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16648  {
16649  assert(firstchange >= 0);
16650 
16651  if( firstchange < nconss && conshdlrdata->presolusehashing )
16652  {
16653  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16654  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16655  ndelconss, nchgsides) );
16656  }
16657 
16658  if( firstchange < nconss && conshdlrdata->presolpairwise )
16659  {
16660  SCIP_CONS** usefulconss;
16661  int nusefulconss;
16662  int firstchangenew;
16663  SCIP_Longint npaircomparisons;
16664 
16665  npaircomparisons = 0;
16666  oldndelconss = *ndelconss;
16667  oldnchgsides = *nchgsides;
16668  oldnchgcoefs = *nchgcoefs;
16669 
16670  /* allocate temporary memory */
16671  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16672 
16673  nusefulconss = 0;
16674  firstchangenew = -1;
16675  for( c = 0; c < nconss; ++c )
16676  {
16677  /* update firstchange */
16678  if( c == firstchange )
16679  firstchangenew = nusefulconss;
16680 
16681  /* ignore inactive and modifiable constraints */
16682  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16683  continue;
16684 
16685  usefulconss[nusefulconss] = conss[c];
16686  ++nusefulconss;
16687  }
16688  firstchange = firstchangenew;
16689  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16690 
16691  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16692  {
16693  /* constraint has become inactive or modifiable during pairwise presolving */
16694  if( usefulconss[c] == NULL )
16695  continue;
16696 
16697  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16698 
16699  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16700  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16701  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16702 
16703  if( npaircomparisons > conshdlrdata->nmincomparisons )
16704  {
16705  assert(npaircomparisons > 0);
16706  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16707  break;
16708  oldndelconss = *ndelconss;
16709  oldnchgsides = *nchgsides;
16710  oldnchgcoefs = *nchgcoefs;
16711  npaircomparisons = 0;
16712  }
16713  }
16714  /* free temporary memory */
16715  SCIPfreeBufferArray(scip, &usefulconss);
16716  }
16717  }
16718 
16719  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16720  * in linear constraints and we therefore have full information about it
16721  */
16722  if( !cutoff && firstupgradetry < nconss
16723  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16724  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16725  )
16726  {
16727  if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16728  {
16729  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16730  }
16731  }
16732 
16733  /* try to upgrade constraints into a more specific constraint type;
16734  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16735  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16736  */
16737  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16738  {
16739  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16740  {
16741  cons = conss[c];
16742 
16743  /* don't upgrade modifiable constraints */
16744  if( SCIPconsIsModifiable(cons) )
16745  continue;
16746 
16747  consdata = SCIPconsGetData(cons);
16748  assert(consdata != NULL);
16749 
16750  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16751  if( consdata->upgradetried )
16752  continue;
16753  /* @todo force that upgrade will be performed later? */
16754  if( !consdata->presolved )
16755  continue;
16756 
16757  consdata->upgradetried = TRUE;
16758  if( SCIPconsIsActive(cons) )
16759  {
16760  SCIP_CONS* upgdcons;
16761 
16762  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16763  if( upgdcons != NULL )
16764  {
16765  /* add the upgraded constraint to the problem */
16766  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16767  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16768  (*nupgdconss)++;
16769 
16770  /* mark the linear constraint being upgraded and to be removed after presolving;
16771  * don't delete it directly, because it may help to preprocess other linear constraints
16772  */
16773  assert(!consdata->upgraded);
16774  consdata->upgraded = TRUE;
16775 
16776  /* delete upgraded inequalities immediately;
16777  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16778  */
16779  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16780  || !conshdlrdata->presolpairwise
16781  || (conshdlrdata->maxaggrnormscale == 0.0) )
16782  {
16783  SCIP_CALL( SCIPdelCons(scip, cons) );
16784  }
16785  }
16786  }
16787  }
16788  }
16789 
16790  /* return the correct result code */
16791  if( cutoff )
16792  *result = SCIP_CUTOFF;
16793  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16794  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16795  *result = SCIP_SUCCESS;
16796  else
16797  *result = SCIP_DIDNOTFIND;
16798 
16799  return SCIP_OKAY;
16800 }
16801 
16802 
16803 /** propagation conflict resolving method of constraint handler */
16804 static
16805 SCIP_DECL_CONSRESPROP(consRespropLinear)
16806 { /*lint --e{715}*/
16807  assert(scip != NULL);
16808  assert(cons != NULL);
16809  assert(result != NULL);
16810 
16811  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16812 
16813  return SCIP_OKAY;
16814 }
16815 
16816 
16817 /** variable rounding lock method of constraint handler */
16818 static
16819 SCIP_DECL_CONSLOCK(consLockLinear)
16820 { /*lint --e{715}*/
16821  SCIP_CONSDATA* consdata;
16822  SCIP_Bool haslhs;
16823  SCIP_Bool hasrhs;
16824  int i;
16825 
16826  assert(scip != NULL);
16827  assert(cons != NULL);
16828  consdata = SCIPconsGetData(cons);
16829  assert(consdata != NULL);
16830 
16831  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16832  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16833 
16834  /* update rounding locks of every single variable */
16835  for( i = 0; i < consdata->nvars; ++i )
16836  {
16837  if( SCIPisPositive(scip, consdata->vals[i]) )
16838  {
16839  if( haslhs )
16840  {
16841  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16842  }
16843  if( hasrhs )
16844  {
16845  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16846  }
16847  }
16848  else
16849  {
16850  if( haslhs )
16851  {
16852  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16853  }
16854  if( hasrhs )
16855  {
16856  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16857  }
16858  }
16859  }
16860 
16861  return SCIP_OKAY;
16862 }
16863 
16864 
16865 /** variable deletion method of constraint handler */
16866 static
16867 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16868 {
16869  assert(scip != NULL);
16870  assert(conshdlr != NULL);
16871  assert(conss != NULL || nconss == 0);
16872 
16873  if( nconss > 0 )
16874  {
16875  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16876  }
16877 
16878  return SCIP_OKAY;
16879 }
16880 
16881 /** constraint display method of constraint handler */
16882 static
16883 SCIP_DECL_CONSPRINT(consPrintLinear)
16884 { /*lint --e{715}*/
16885  assert(scip != NULL);
16886  assert(conshdlr != NULL);
16887  assert(cons != NULL);
16888 
16889  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16890 
16891  return SCIP_OKAY;
16892 }
16893 
16894 /** constraint copying method of constraint handler */
16895 static
16896 SCIP_DECL_CONSCOPY(consCopyLinear)
16897 { /*lint --e{715}*/
16898  SCIP_VAR** sourcevars;
16899  SCIP_Real* sourcecoefs;
16900  const char* consname;
16901  int nvars;
16903  assert(scip != NULL);
16904  assert(sourcescip != NULL);
16905  assert(sourcecons != NULL);
16906 
16907  /* get variables and coefficients of the source constraint */
16908  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16909  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16910  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16911 
16912  if( name != NULL )
16913  consname = name;
16914  else
16915  consname = SCIPconsGetName(sourcecons);
16916 
16917  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16918  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16919  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16920  assert(cons != NULL || *valid == FALSE);
16921 
16922  /* @todo should also the checkabsolute flag of the constraint be copied? */
16923 
16924  return SCIP_OKAY;
16925 }
16926 
16927 /** find operators '<=', '==', '>=', [free] in input string and return those places
16928  *
16929  * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16930  */
16931 static
16932 void findOperators(
16933  const char* str, /**< null terminated input string */
16934  char** firstoperator, /**< pointer to store the string starting at the first operator */
16935  char** secondoperator, /**< pointer to store the string starting at the second operator */
16936  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16937  )
16938 {
16939  char* curr;
16940 
16941  assert(str != NULL);
16942  assert(firstoperator != NULL);
16943  assert(secondoperator != NULL);
16944 
16945  *firstoperator = NULL;
16946  *secondoperator = NULL;
16947 
16948  curr = (char*)str;
16949  *success = TRUE;
16950 
16951  /* loop over the input string to find all operators */
16952  while( *curr && *success )
16953  {
16954  SCIP_Bool found = FALSE;
16955  int increment = 1;
16956 
16957  /* try if we found a possible operator */
16958  switch( *curr )
16959  {
16960  case '<':
16961  case '=':
16962  case '>':
16963 
16964  /* check if the two characters curr[0,1] form an operator together */
16965  if( curr[1] == '=' )
16966  {
16967  found = TRUE;
16968 
16969  /* update increment to continue after this operator */
16970  increment = 2;
16971  }
16972  break;
16973  case '[':
16974  if( strncmp(curr, "[free]", 6) == 0 )
16975  {
16976  found = TRUE;
16977 
16978  /* update increment to continue after this operator */
16979  increment = 6;
16980  }
16981  break;
16982  default:
16983  break;
16984  }
16985 
16986  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16987  if( found )
16988  {
16989  if( *firstoperator == NULL )
16990  {
16991  *firstoperator = curr;
16992  }
16993  else
16994  {
16995  if( *secondoperator != NULL )
16996  {
16997  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16998  *success = FALSE;
16999  }
17000  else if( strncmp(*firstoperator, "<=", 2) != 0 )
17001  {
17002  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17003  *success = FALSE;
17004  }
17005  else if( strncmp(curr, "<=", 2) != 0 )
17006  {
17007  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17008  *success = FALSE;
17009  }
17010 
17011  *secondoperator = curr;
17012  }
17013  }
17014 
17015  curr += increment;
17016  }
17017 
17018  /* check if we did find at least one operator */
17019  if( *success )
17020  {
17021  if( *firstoperator == NULL )
17022  {
17023  SCIPerrorMessage("Could not find any operator in line %s\n", str);
17024  *success = FALSE;
17025  }
17026  }
17027 }
17028 
17029 /** constraint parsing method of constraint handler */
17030 static
17031 SCIP_DECL_CONSPARSE(consParseLinear)
17032 { /*lint --e{715}*/
17033  SCIP_VAR** vars;
17034  SCIP_Real* coefs;
17035  int nvars;
17036  int coefssize;
17037  int requsize;
17038  SCIP_Real lhs;
17039  SCIP_Real rhs;
17040  char* endptr;
17041  char* firstop;
17042  char* secondop;
17043  SCIP_Bool operatorsuccess;
17044  char* lhsstrptr;
17045  char* rhsstrptr;
17046  char* varstrptr;
17047 
17048  assert(scip != NULL);
17049  assert(success != NULL);
17050  assert(str != NULL);
17051  assert(name != NULL);
17052  assert(cons != NULL);
17053 
17054  /* set left and right hand side to their default values */
17055  lhs = -SCIPinfinity(scip);
17056  rhs = SCIPinfinity(scip);
17057 
17058  (*success) = FALSE;
17059 
17060  /* return of string empty */
17061  if( !*str )
17062  return SCIP_OKAY;
17063 
17064  /* ignore whitespace */
17065  while( isspace((unsigned char)*str) )
17066  ++str;
17067 
17068  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17069  * and the special word [free]
17070  */
17071  findOperators(str, &firstop, &secondop, &operatorsuccess);
17072 
17073  /* if the grammar is not valid for parsing a linear constraint, return */
17074  if( ! operatorsuccess )
17075  return SCIP_OKAY;
17076 
17077  varstrptr = (char *)str;
17078  lhsstrptr = rhsstrptr = NULL;
17079  assert(firstop != NULL);
17080 
17081  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17082  switch( *firstop )
17083  {
17084  case '<':
17085  assert(firstop[1] == '=');
17086  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17087  if( secondop != NULL )
17088  {
17089  assert(secondop[0] == '<' && secondop[1] == '=');
17090  lhsstrptr = (char *)str;
17091  varstrptr = firstop + 2;
17092  rhsstrptr = secondop + 2;
17093  }
17094  else
17095  {
17096  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17097  lhsstrptr = NULL;
17098  varstrptr = (char *)str;
17099  rhsstrptr = firstop + 2;
17100  }
17101  break;
17102  case '>':
17103  assert(firstop[1] == '=');
17104  assert(secondop == NULL);
17105  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17106  lhsstrptr = firstop + 2;
17107  break;
17108  case '=':
17109  assert(firstop[1] == '=');
17110  assert(secondop == NULL);
17111  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17112  rhsstrptr = firstop + 2;
17113  lhsstrptr = firstop + 2;
17114  break;
17115  case '[':
17116  assert(strncmp(firstop, "[free]", 6) == 0);
17117  assert(secondop == NULL);
17118  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17119  break;
17120  default:
17121  /* it should not be possible that a different character appears in that position */
17122  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17123  return SCIP_READERROR;
17124  }
17125 
17126  /* parse left hand side, if necessary */
17127  if( lhsstrptr != NULL )
17128  {
17129  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17130  {
17131  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17132  return SCIP_OKAY;
17133  }
17134 
17135  /* in case of an equation, assign the left also to the right hand side */
17136  if( rhsstrptr == lhsstrptr )
17137  rhs = lhs;
17138  }
17139 
17140  /* parse right hand side, if different from left hand side */
17141  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17142  {
17143  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17144  {
17145  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17146  return SCIP_OKAY;
17147  }
17148  }
17149 
17150  /* initialize buffers for storing the variables and coefficients */
17151  coefssize = 100;
17152  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17153  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17154 
17155  assert(varstrptr != NULL);
17156 
17157  /* parse linear sum to get variables and coefficients */
17158  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17159 
17160  if( *success && requsize > coefssize )
17161  {
17162  /* realloc buffers and try again */
17163  coefssize = requsize;
17164  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17165  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17166 
17167  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17168  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17169  }
17170 
17171  if( !*success )
17172  {
17173  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17174  }
17175  else
17176  {
17177  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17178  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17179  }
17180 
17181  SCIPfreeBufferArray(scip, &coefs);
17182  SCIPfreeBufferArray(scip, &vars);
17183 
17184  return SCIP_OKAY;
17185 }
17186 
17187 
17188 /** constraint method of constraint handler which returns the variables (if possible) */
17189 static
17190 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17191 { /*lint --e{715}*/
17192  SCIP_CONSDATA* consdata;
17193 
17194  consdata = SCIPconsGetData(cons);
17195  assert(consdata != NULL);
17196 
17197  if( varssize < consdata->nvars )
17198  (*success) = FALSE;
17199  else
17200  {
17201  assert(vars != NULL);
17202 
17203  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17204  (*success) = TRUE;
17205  }
17206 
17207  return SCIP_OKAY;
17208 }
17210 /**! [Callback for the number of variables]*/
17211 /** constraint method of constraint handler which returns the number of variables (if possible) */
17212 static
17213 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17214 { /*lint --e{715}*/
17215  SCIP_CONSDATA* consdata;
17216 
17217  consdata = SCIPconsGetData(cons);
17218  assert(consdata != NULL);
17219 
17220  (*nvars) = consdata->nvars;
17221  (*success) = TRUE;
17222 
17223  return SCIP_OKAY;
17224 }
17225 /**! [Callback for the number of variables]*/
17226 
17227 /*
17228  * Callback methods of event handler
17229  */
17230 
17231 /** execution method of event handler */
17232 static
17233 SCIP_DECL_EVENTEXEC(eventExecLinear)
17234 { /*lint --e{715}*/
17235  SCIP_CONS* cons;
17236  SCIP_CONSDATA* consdata;
17237  SCIP_VAR* var;
17238  SCIP_EVENTTYPE eventtype;
17239 
17240  assert(scip != NULL);
17241  assert(eventhdlr != NULL);
17242  assert(eventdata != NULL);
17243  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17244  assert(event != NULL);
17245 
17246  cons = eventdata->cons;
17247  assert(cons != NULL);
17248  consdata = SCIPconsGetData(cons);
17249  assert(consdata != NULL);
17250 
17251  /* we can skip events droped for deleted constraints */
17252  if( SCIPconsIsDeleted(cons) )
17253  return SCIP_OKAY;
17254 
17255  eventtype = SCIPeventGetType(event);
17256  var = SCIPeventGetVar(event);
17257 
17258  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17259  {
17260  SCIP_Real oldbound;
17261  SCIP_Real newbound;
17262  SCIP_Real val;
17263  int varpos;
17264 
17265  varpos = eventdata->varpos;
17266  assert(0 <= varpos && varpos < consdata->nvars);
17267  oldbound = SCIPeventGetOldbound(event);
17268  newbound = SCIPeventGetNewbound(event);
17269  assert(var != NULL);
17270  assert(consdata->vars[varpos] == var);
17271  val = consdata->vals[varpos];
17272 
17273  /* we only need to update the activities if the constraint is active,
17274  * otherwise we mark them to be invalid
17275  */
17276  if( SCIPconsIsActive(cons) )
17277  {
17278  /* update the activity values */
17279  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17280  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17281  else
17282  {
17283  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17284  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17285  }
17286  }
17287  else
17288  consdataInvalidateActivities(consdata);
17289 
17290  consdata->presolved = FALSE;
17291  consdata->rangedrowpropagated = 0;
17292 
17293  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17294  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17295  {
17296  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17297 
17298  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17299  if( consdata->maxactdeltavar == var )
17300  {
17301  consdata->maxactdelta = SCIP_INVALID;
17302  consdata->maxactdeltavar = NULL;
17303  }
17304 
17305  /* check whether bound tightening might now be successful */
17306  if( consdata->boundstightened > 0)
17307  {
17308  switch( eventtype )
17309  {
17311  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17312  consdata->boundstightened = 0;
17313  break;
17315  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17316  consdata->boundstightened = 0;
17317  break;
17318  default:
17319  SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17320  return SCIP_INVALIDDATA;
17321  }
17322  }
17323  }
17324  /* update maximal activity delta if a bound was relaxed */
17325  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17326  {
17327  SCIP_Real lb;
17328  SCIP_Real ub;
17329  SCIP_Real domain;
17330  SCIP_Real delta;
17331 
17332  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17333 
17334  lb = SCIPvarGetLbLocal(var);
17335  ub = SCIPvarGetUbLocal(var);
17336 
17337  domain = ub - lb;
17338  delta = REALABS(val) * domain;
17339 
17340  if( delta > consdata->maxactdelta )
17341  {
17342  consdata->maxactdelta = delta;
17343  consdata->maxactdeltavar = var;
17344  }
17345  }
17346  }
17347  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17348  {
17349  /* we want to remove the fixed variable */
17350  consdata->presolved = FALSE;
17351  consdata->removedfixings = FALSE;
17352  consdata->rangedrowpropagated = 0;
17353 
17354  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17355  if( consdata->maxactdeltavar == var )
17356  {
17357  consdata->maxactdelta = SCIP_INVALID;
17358  consdata->maxactdeltavar = NULL;
17359  }
17360  }
17361  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17362  {
17363  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17364  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17365  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17366  consdata->presolved = FALSE;
17367  }
17368  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17369  {
17370  SCIP_Real oldbound;
17371  SCIP_Real newbound;
17372  SCIP_Real val;
17373  int varpos;
17374 
17375  varpos = eventdata->varpos;
17376  assert(0 <= varpos && varpos < consdata->nvars);
17377  oldbound = SCIPeventGetOldbound(event);
17378  newbound = SCIPeventGetNewbound(event);
17379  assert(var != NULL);
17380  assert(consdata->vars[varpos] == var);
17381  val = consdata->vals[varpos];
17382 
17383  consdata->rangedrowpropagated = 0;
17384 
17385  /* update the activity values */
17386  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17387  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17388  else
17389  {
17390  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17391  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17392  }
17393 
17394  /* if the variable is binary but not fixed it had to become binary due to this global change */
17395  if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17396  {
17397  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17398  consdata->indexsorted = FALSE;
17399  else
17400  consdata->coefsorted = FALSE;
17401  }
17402  }
17403  else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17404  {
17405  assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17406 
17407  /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17408  consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17409 
17410  /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17411  consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17412  }
17413  else
17414  {
17415  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17416  consdata->varsdeleted = TRUE;
17417  }
17418 
17419  return SCIP_OKAY;
17420 }
17421 
17422 
17423 /*
17424  * Callback methods of conflict handler
17425  */
17426 
17427 /** conflict processing method of conflict handler (called when conflict was found) */
17428 static
17429 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17430 { /*lint --e{715}*/
17431  SCIP_VAR** vars;
17432  SCIP_Real* vals;
17433  SCIP_Real lhs;
17434  int i;
17435 
17436  assert(scip != NULL);
17437  assert(conflicthdlr != NULL);
17438  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17439  assert(bdchginfos != NULL || nbdchginfos == 0);
17440  assert(result != NULL);
17441 
17442  /* don't process already resolved conflicts */
17443  if( resolved )
17444  {
17445  *result = SCIP_DIDNOTRUN;
17446  return SCIP_OKAY;
17447  }
17449  *result = SCIP_DIDNOTFIND;
17450 
17451  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17452  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17453  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17454  lhs = 1.0;
17455  for( i = 0; i < nbdchginfos; ++i )
17456  {
17457  assert(bdchginfos != NULL);
17458 
17459  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17460 
17461  /* we can only treat binary variables */
17462  /**@todo extend linear conflict constraints to some non-binary cases */
17463  if( !SCIPvarIsBinary(vars[i]) )
17464  break;
17465 
17466  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17467  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17468  vals[i] = 1.0;
17469  else
17470  {
17471  vals[i] = -1.0;
17472  lhs -= 1.0;
17473  }
17474  }
17475 
17476  if( i == nbdchginfos )
17477  {
17478  SCIP_CONS* cons;
17479  SCIP_CONS* upgdcons;
17480  char consname[SCIP_MAXSTRLEN];
17481 
17482  /* create a constraint out of the conflict set */
17483  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17484  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17485  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17486 
17487  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17488  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17489  if( upgdcons != NULL )
17490  {
17491  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17492  cons = upgdcons;
17493  }
17494 
17495  /* add conflict to SCIP */
17496  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17497 
17498  *result = SCIP_CONSADDED;
17499  }
17500 
17501  /* free temporary memory */
17502  SCIPfreeBufferArray(scip, &vals);
17503  SCIPfreeBufferArray(scip, &vars);
17504 
17505  return SCIP_OKAY;
17506 }
17507 
17508 
17509 /*
17510  * Nonlinear constraint upgrading
17511  */
17512 
17513 /** tries to upgrade a nonlinear constraint into a linear constraint */
17514 static
17515 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17516 {
17517  SCIP_CONSDATA* consdata;
17518  SCIP_EXPR* expr;
17519  SCIP_Real lhs;
17520  SCIP_Real rhs;
17521  int i;
17522 
17523  assert(nupgdconss != NULL);
17524  assert(upgdconss != NULL);
17525  assert(upgdconsssize > 0);
17526 
17527  expr = SCIPgetExprNonlinear(cons);
17528  assert(expr != NULL);
17529 
17530  /* not a linear constraint if the expression is not a sum
17531  * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17532  */
17533  if( !SCIPisExprSum(scip, expr) )
17534  return SCIP_OKAY;
17535 
17536  /* if at least one child is not a variable, then not a linear constraint */
17537  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17538  if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17539  return SCIP_OKAY;
17540 
17541  /* consider constant part of the sum expression */
17542  lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17543  rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17544 
17545  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17546  0, NULL, NULL, lhs, rhs,
17550  SCIPconsIsStickingAtNode(cons)) );
17551  assert(upgdconss[0] != NULL);
17552 
17553  consdata = SCIPconsGetData(upgdconss[0]);
17554 
17555  /* add linear terms */
17556  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) );
17557  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17558  {
17559  SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) );
17560  }
17561 
17562  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17563  consdata->checkabsolute = TRUE;
17564 
17565  *nupgdconss = 1;
17566 
17567  SCIPdebugMsg(scip, "created linear constraint:\n");
17568  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17569 
17570  return SCIP_OKAY;
17571 } /*lint !e715*/
17572 
17573 /*
17574  * constraint specific interface methods
17575  */
17576 
17577 /** creates the handler for linear constraints and includes it in SCIP */
17579  SCIP* scip /**< SCIP data structure */
17580  )
17581 {
17582  SCIP_CONSHDLRDATA* conshdlrdata;
17583  SCIP_CONSHDLR* conshdlr;
17584  SCIP_EVENTHDLR* eventhdlr;
17585  SCIP_CONFLICTHDLR* conflicthdlr;
17586 
17587  assert(scip != NULL);
17588 
17589  /* create event handler for bound change events */
17591  eventExecLinear, NULL) );
17592 
17593  /* create conflict handler for linear constraints */
17595  conflictExecLinear, NULL) );
17596 
17597  /* create constraint handler data */
17598  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17599 
17600  /* include constraint handler */
17603  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17604  conshdlrdata) );
17605 
17606  assert(conshdlr != NULL);
17607 
17608  /* set non-fundamental callbacks via specific setter functions */
17609  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17610  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17611  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17612  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17613  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17614  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17615  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17616  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17617  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17618  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17619  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17620  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17621  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17622  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17623  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17624  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17625  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17626  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17628  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17629  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17631  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17632  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17633 
17634  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17635  {
17636  /* include the linear constraint upgrade in the nonlinear constraint handler */
17638  }
17639 
17640  /* add linear constraint handler parameters */
17641  SCIP_CALL( SCIPaddIntParam(scip,
17642  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17643  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17644  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17645  SCIP_CALL( SCIPaddIntParam(scip,
17646  "constraints/" CONSHDLR_NAME "/maxrounds",
17647  "maximal number of separation rounds per node (-1: unlimited)",
17648  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17649  SCIP_CALL( SCIPaddIntParam(scip,
17650  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17651  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17652  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17653  SCIP_CALL( SCIPaddIntParam(scip,
17654  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17655  "maximal number of cuts separated per separation round",
17656  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17657  SCIP_CALL( SCIPaddIntParam(scip,
17658  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17659  "maximal number of cuts separated per separation round in the root node",
17660  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17662  "constraints/" CONSHDLR_NAME "/presolpairwise",
17663  "should pairwise constraint comparison be performed in presolving?",
17664  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17666  "constraints/" CONSHDLR_NAME "/presolusehashing",
17667  "should hash table be used for detecting redundant constraints in advance",
17668  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17669  SCIP_CALL( SCIPaddIntParam(scip,
17670  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17671  "number for minimal pairwise presolve comparisons",
17672  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17674  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17675  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17676  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17678  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17679  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17680  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17682  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17683  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17684  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17686  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17687  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17688  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17690  "constraints/" CONSHDLR_NAME "/separateall",
17691  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17692  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17694  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17695  "should presolving search for aggregations in equations",
17696  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17698  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17699  "should presolving try to simplify inequalities",
17700  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17702  "constraints/" CONSHDLR_NAME "/dualpresolving",
17703  "should dual presolving steps be performed?",
17704  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17706  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17707  "should stuffing of singleton continuous variables be performed?",
17708  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17710  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17711  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17712  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17714  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17715  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17717  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17718  "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)?",
17719  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17721  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17722  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17723  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17725  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17726  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17727  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17729  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17730  "should presolving try to detect subsets of constraints parallel to the objective function?",
17731  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17733  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17734  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17735  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17737  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17738  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17739  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17740  SCIP_CALL( SCIPaddIntParam(scip,
17741  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17742  "maximum depth to apply ranged row propagation",
17743  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17744  SCIP_CALL( SCIPaddIntParam(scip,
17745  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17746  "frequency for applying ranged row propagation",
17747  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17749  "constraints/" CONSHDLR_NAME "/multaggrremove",
17750  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17751  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17753  "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17754  "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17755  &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17757  "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17758  "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17759  &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17761  "constraints/" CONSHDLR_NAME "/extractcliques",
17762  "should Cliques be extracted?",
17763  &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17764 
17765  return SCIP_OKAY;
17766 }
17767 
17768 /** includes a linear constraint update method into the linear constraint handler */
17770  SCIP* scip, /**< SCIP data structure */
17771  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17772  int priority, /**< priority of upgrading method */
17773  const char* conshdlrname /**< name of the constraint handler */
17774  )
17775 {
17776  SCIP_CONSHDLR* conshdlr;
17777  SCIP_CONSHDLRDATA* conshdlrdata;
17778  SCIP_LINCONSUPGRADE* linconsupgrade;
17779  char paramname[SCIP_MAXSTRLEN];
17780  char paramdesc[SCIP_MAXSTRLEN];
17781 
17782  assert(scip != NULL);
17783  assert(linconsupgd != NULL);
17784  assert(conshdlrname != NULL );
17785 
17786  /* find the linear constraint handler */
17787  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17788  if( conshdlr == NULL )
17789  {
17790  SCIPerrorMessage("linear constraint handler not found\n");
17791  return SCIP_PLUGINNOTFOUND;
17792  }
17793 
17794  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17795  assert(conshdlrdata != NULL);
17796 
17797  /* check if linear constraint update method already exists in constraint handler data */
17798  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17799  {
17800  /* create a linear constraint upgrade data object */
17801  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17802 
17803  /* insert linear constraint update method into constraint handler data */
17804  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17805 
17806  /* adds parameter to turn on and off the upgrading step */
17807  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17808  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17810  paramname, paramdesc,
17811  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17812  }
17813 
17814  return SCIP_OKAY;
17815 }
17816 
17817 /** creates and captures a linear constraint
17818  *
17819  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17820  */
17822  SCIP* scip, /**< SCIP data structure */
17823  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17824  const char* name, /**< name of constraint */
17825  int nvars, /**< number of nonzeros in the constraint */
17826  SCIP_VAR** vars, /**< array with variables of constraint entries */
17827  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17828  SCIP_Real lhs, /**< left hand side of constraint */
17829  SCIP_Real rhs, /**< right hand side of constraint */
17830  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17831  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17832  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17833  * Usually set to TRUE. */
17834  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17835  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17836  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17837  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17838  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17839  * Usually set to TRUE. */
17840  SCIP_Bool local, /**< is constraint only valid locally?
17841  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17842  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17843  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17844  * adds coefficients to this constraint. */
17845  SCIP_Bool dynamic, /**< is constraint subject to aging?
17846  * Usually set to FALSE. Set to TRUE for own cuts which
17847  * are separated as constraints. */
17848  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17849  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17850  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17851  * if it may be moved to a more global node?
17852  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17853  )
17854 {
17855  SCIP_CONSHDLR* conshdlr;
17856  SCIP_CONSDATA* consdata;
17857 
17858  assert(scip != NULL);
17859  assert(cons != NULL);
17860 
17861  /* find the linear constraint handler */
17862  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17863  if( conshdlr == NULL )
17864  {
17865  SCIPerrorMessage("linear constraint handler not found\n");
17866  return SCIP_PLUGINNOTFOUND;
17867  }
17868 
17869  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17870  * constraint after presolving we have to ensure that it holds active variables
17871  */
17872  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17873  {
17874  SCIP_VAR** consvars;
17875  SCIP_Real* consvals;
17876  SCIP_Real constant = 0.0;
17877  int nconsvars;
17878  int requiredsize;
17879 
17880  nconsvars = nvars;
17881  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17882  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17883 
17884  /* get active variables for new constraint */
17885  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17886 
17887  /* if space was not enough we need to resize the buffers */
17888  if( requiredsize > nconsvars )
17889  {
17890  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17891  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17892 
17893  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17894  assert(requiredsize <= nconsvars);
17895  }
17896 
17897  /* adjust sides and check that we do not subtract infinity values */
17898  if( SCIPisInfinity(scip, REALABS(constant)) )
17899  {
17900  if( constant < 0.0 )
17901  {
17902  if( SCIPisInfinity(scip, lhs) )
17903  {
17904  SCIPfreeBufferArray(scip, &consvals);
17905  SCIPfreeBufferArray(scip, &consvars);
17906 
17907  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);
17908 
17909  SCIPABORT();
17910  return SCIP_INVALIDDATA; /*lint !e527*/
17911  }
17912  if( SCIPisInfinity(scip, rhs) )
17913  {
17914  SCIPfreeBufferArray(scip, &consvals);
17915  SCIPfreeBufferArray(scip, &consvars);
17916 
17917  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);
17918 
17919  SCIPABORT();
17920  return SCIP_INVALIDDATA; /*lint !e527*/
17921  }
17922 
17923  lhs = -SCIPinfinity(scip);
17924  rhs = -SCIPinfinity(scip);
17925  }
17926  else
17927  {
17928  if( SCIPisInfinity(scip, -lhs) )
17929  {
17930  SCIPfreeBufferArray(scip, &consvals);
17931  SCIPfreeBufferArray(scip, &consvars);
17932 
17933  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);
17934 
17935  SCIPABORT();
17936  return SCIP_INVALIDDATA; /*lint !e527*/
17937  }
17938  if( SCIPisInfinity(scip, -rhs) )
17939  {
17940  SCIPfreeBufferArray(scip, &consvals);
17941  SCIPfreeBufferArray(scip, &consvars);
17942 
17943  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);
17944 
17945  SCIPABORT();
17946  return SCIP_INVALIDDATA; /*lint !e527*/
17947  }
17948 
17949  lhs = SCIPinfinity(scip);
17950  rhs = SCIPinfinity(scip);
17951  }
17952  }
17953  else
17954  {
17955  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17956  lhs -= constant;
17957  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17958  rhs -= constant;
17959 
17960  if( SCIPisInfinity(scip, -lhs) )
17961  lhs = -SCIPinfinity(scip);
17962  else if( SCIPisInfinity(scip, lhs) )
17963  lhs = SCIPinfinity(scip);
17964 
17965  if( SCIPisInfinity(scip, rhs) )
17966  rhs = SCIPinfinity(scip);
17967  else if( SCIPisInfinity(scip, -rhs) )
17968  rhs = -SCIPinfinity(scip);
17969  }
17970 
17971  /* create constraint data */
17972  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17973  assert(consdata != NULL);
17974 
17975  SCIPfreeBufferArray(scip, &consvals);
17976  SCIPfreeBufferArray(scip, &consvars);
17977  }
17978  else
17979  {
17980  /* create constraint data */
17981  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17982  assert(consdata != NULL);
17983  }
17984 
17985 #ifndef NDEBUG
17986  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
17987  if( check || enforce )
17988  {
17989  int n;
17990  for(n = consdata->nvars - 1; n >= 0; --n )
17991  assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
17992  }
17993 #endif
17994 
17995  /* create constraint */
17996  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17997  local, modifiable, dynamic, removable, stickingatnode) );
17998 
17999  return SCIP_OKAY;
18000 }
18001 
18002 /** creates and captures a linear constraint
18003  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18004  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18005  *
18006  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18007  *
18008  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18009  */
18011  SCIP* scip, /**< SCIP data structure */
18012  SCIP_CONS** cons, /**< pointer to hold the created constraint */
18013  const char* name, /**< name of constraint */
18014  int nvars, /**< number of nonzeros in the constraint */
18015  SCIP_VAR** vars, /**< array with variables of constraint entries */
18016  SCIP_Real* vals, /**< array with coefficients of constraint entries */
18017  SCIP_Real lhs, /**< left hand side of constraint */
18018  SCIP_Real rhs /**< right hand side of constraint */
18019  )
18020 {
18021  assert(scip != NULL);
18022 
18023  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18024  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
18025 
18026  return SCIP_OKAY;
18027 }
18028 
18029 /** creates by copying and captures a linear constraint */
18031  SCIP* scip, /**< target SCIP data structure */
18032  SCIP_CONS** cons, /**< pointer to store the created target constraint */
18033  SCIP* sourcescip, /**< source SCIP data structure */
18034  const char* name, /**< name of constraint */
18035  int nvars, /**< number of variables in source variable array */
18036  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18037  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18038  SCIP_Real lhs, /**< left hand side of the linear constraint */
18039  SCIP_Real rhs, /**< right hand side of the linear constraint */
18040  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18041  * variables of the target SCIP */
18042  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18043  * target constraints */
18044  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18045  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18046  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18047  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18048  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18049  SCIP_Bool local, /**< is constraint only valid locally? */
18050  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18051  SCIP_Bool dynamic, /**< is constraint subject to aging? */
18052  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18053  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18054  * if it may be moved to a more global node? */
18055  SCIP_Bool global, /**< create a global or a local copy? */
18056  SCIP_Bool* valid /**< pointer to store if the copying was valid */
18057  )
18058 {
18059  SCIP_VAR** vars;
18060  SCIP_Real* coefs;
18061 
18062  SCIP_Real constant;
18063  int requiredsize;
18064  int v;
18065  SCIP_Bool success;
18066 
18067  if( SCIPisGT(scip, lhs, rhs) )
18068  {
18069  *valid = FALSE;
18070  return SCIP_OKAY;
18071  }
18072 
18073  (*valid) = TRUE;
18074 
18075  if( nvars == 0 )
18076  {
18077  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18078  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18079  return SCIP_OKAY;
18080  }
18081 
18082  /* duplicate variable array */
18083  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18084 
18085  /* duplicate coefficient array */
18086  if( sourcecoefs != NULL )
18087  {
18088  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18089  }
18090  else
18091  {
18092  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18093  for( v = 0; v < nvars; ++v )
18094  coefs[v] = 1.0;
18095  }
18096 
18097  constant = 0.0;
18098 
18099  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18100  * the target SCIP
18101  */
18102  if( !SCIPvarIsOriginal(vars[0]) )
18103  {
18104  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18105 
18106  if( requiredsize > nvars )
18107  {
18108  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18109  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18110 
18111  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18112  assert(requiredsize <= nvars);
18113  }
18114  }
18115  else
18116  {
18117  for( v = 0; v < nvars; ++v )
18118  {
18119  assert(SCIPvarIsOriginal(vars[v]));
18120  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18121  assert(vars[v] != NULL);
18122  }
18123  }
18124 
18125  success = TRUE;
18126  /* map variables of the source constraint to variables of the target SCIP */
18127  for( v = 0; v < nvars && success; ++v )
18128  {
18129  SCIP_VAR* var;
18130  var = vars[v];
18131 
18132  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18133  assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18134 
18135  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18136  assert(!(success) || vars[v] != NULL);
18137  }
18138 
18139  /* only create the target constraint, if all variables could be copied */
18140  if( success )
18141  {
18142  if( !SCIPisInfinity(scip, -lhs) )
18143  lhs -= constant;
18144 
18145  if( !SCIPisInfinity(scip, rhs) )
18146  rhs -= constant;
18147 
18148  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18149  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18150  }
18151  else
18152  *valid = FALSE;
18153 
18154  /* free buffer array */
18155  SCIPfreeBufferArray(scip, &coefs);
18156  SCIPfreeBufferArray(scip, &vars);
18157 
18158  return SCIP_OKAY;
18159 }
18160 
18161 /** adds coefficient to linear constraint (if it is not zero) */
18163  SCIP* scip, /**< SCIP data structure */
18164  SCIP_CONS* cons, /**< constraint data */
18165  SCIP_VAR* var, /**< variable of constraint entry */
18166  SCIP_Real val /**< coefficient of constraint entry */
18167  )
18168 {
18169  assert(scip != NULL);
18170  assert(cons != NULL);
18171  assert(var != NULL);
18172 
18173  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18174  {
18175  SCIPerrorMessage("constraint is not linear\n");
18176  return SCIP_INVALIDDATA;
18177  }
18178 
18179  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18180  * constraint after presolving we have to ensure that it holds active variables
18181  */
18182  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18183  {
18184  SCIP_CONSDATA* consdata;
18185  SCIP_VAR** consvars;
18186  SCIP_Real* consvals;
18187  SCIP_Real constant = 0.0;
18188  SCIP_Real rhs;
18189  SCIP_Real lhs;
18190  int nconsvars;
18191  int requiredsize;
18192  int v;
18193 
18194  nconsvars = 1;
18195  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18196  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18197  consvars[0] = var;
18198  consvals[0] = val;
18199 
18200  /* get active variables for new constraint */
18201  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18202 
18203  /* if space was not enough we need to resize the buffers */
18204  if( requiredsize > nconsvars )
18205  {
18206  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18207  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18208 
18209  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18210  assert(requiredsize <= nconsvars);
18211  }
18212 
18213  consdata = SCIPconsGetData(cons);
18214  assert(consdata != NULL);
18215 
18216  lhs = consdata->lhs;
18217  rhs = consdata->rhs;
18218 
18219  /* adjust sides and check that we do not subtract infinity values */
18220  /* constant is infinite */
18221  if( SCIPisInfinity(scip, REALABS(constant)) )
18222  {
18223  if( constant < 0.0 )
18224  {
18225  if( SCIPisInfinity(scip, lhs) )
18226  {
18227  SCIPfreeBufferArray(scip, &consvals);
18228  SCIPfreeBufferArray(scip, &consvars);
18229 
18230  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));
18231 
18232  SCIPABORT();
18233  return SCIP_INVALIDDATA; /*lint !e527*/
18234  }
18235  if( SCIPisInfinity(scip, rhs) )
18236  {
18237  SCIPfreeBufferArray(scip, &consvals);
18238  SCIPfreeBufferArray(scip, &consvars);
18239 
18240  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));
18241 
18242  SCIPABORT();
18243  return SCIP_INVALIDDATA; /*lint !e527*/
18244  }
18245 
18246  lhs = -SCIPinfinity(scip);
18247  rhs = -SCIPinfinity(scip);
18248  }
18249  else
18250  {
18251  if( SCIPisInfinity(scip, -lhs) )
18252  {
18253  SCIPfreeBufferArray(scip, &consvals);
18254  SCIPfreeBufferArray(scip, &consvars);
18255 
18256  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));
18257 
18258  SCIPABORT();
18259  return SCIP_INVALIDDATA; /*lint !e527*/
18260  }
18261  if( SCIPisInfinity(scip, -rhs) )
18262  {
18263  SCIPfreeBufferArray(scip, &consvals);
18264  SCIPfreeBufferArray(scip, &consvars);
18265 
18266  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));
18267 
18268  SCIPABORT();
18269  return SCIP_INVALIDDATA; /*lint !e527*/
18270  }
18271 
18272  lhs = SCIPinfinity(scip);
18273  rhs = SCIPinfinity(scip);
18274  }
18275  }
18276  /* constant is not infinite */
18277  else
18278  {
18279  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18280  lhs -= constant;
18281  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18282  rhs -= constant;
18283 
18284  if( SCIPisInfinity(scip, -lhs) )
18285  lhs = -SCIPinfinity(scip);
18286  else if( SCIPisInfinity(scip, lhs) )
18287  lhs = SCIPinfinity(scip);
18288 
18289  if( SCIPisInfinity(scip, rhs) )
18290  rhs = SCIPinfinity(scip);
18291  else if( SCIPisInfinity(scip, -rhs) )
18292  rhs = -SCIPinfinity(scip);
18293  }
18294 
18295  /* add all active variables to constraint */
18296  for( v = nconsvars - 1; v >= 0; --v )
18297  {
18298  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18299  }
18300 
18301  /* update left and right hand sides */
18302  SCIP_CALL( chgLhs(scip, cons, lhs));
18303  SCIP_CALL( chgRhs(scip, cons, rhs));
18304 
18305  SCIPfreeBufferArray(scip, &consvals);
18306  SCIPfreeBufferArray(scip, &consvars);
18307  }
18308  else
18309  {
18310  SCIP_CALL( addCoef(scip, cons, var, val) );
18311  }
18312 
18313  return SCIP_OKAY;
18314 }
18315 
18316 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18317  * not yet contained in the constraint
18318  *
18319  * @note This method may only be called during problem creation stage for an original constraint and variable.
18320  *
18321  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18322  */
18324  SCIP* scip, /**< SCIP data structure */
18325  SCIP_CONS* cons, /**< constraint data */
18326  SCIP_VAR* var, /**< variable of constraint entry */
18327  SCIP_Real val /**< new coefficient of constraint entry */
18328  )
18329 {
18330  SCIP_CONSDATA* consdata;
18331  SCIP_VAR** vars;
18332  SCIP_Bool found;
18333  int i;
18334 
18335  assert(scip != NULL);
18336  assert(cons != NULL);
18337  assert(var != NULL);
18338 
18339  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18340  {
18341  SCIPerrorMessage("constraint is not linear\n");
18343  }
18344 
18345  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18346  {
18347  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18348  return SCIP_INVALIDDATA;
18349  }
18350 
18351  consdata = SCIPconsGetData(cons);
18352  assert(consdata != NULL);
18353 
18354  vars = consdata->vars;
18355  found = FALSE;
18356  i = 0;
18357  while( i < consdata->nvars )
18358  {
18359  if( vars[i] == var )
18360  {
18361  if( found || SCIPisZero(scip, val) )
18362  {
18363  SCIP_CALL( delCoefPos(scip, cons, i) );
18364 
18365  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18366  i--;
18367  }
18368  else
18369  {
18370  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18371  }
18372  found = TRUE;
18373  }
18374  i++;
18375  }
18376 
18377  if( !found && !SCIPisZero(scip, val) )
18378  {
18379  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18380  }
18381 
18382  return SCIP_OKAY;
18383 }
18384 
18385 /** deletes variable from linear constraint
18386  *
18387  * @note This method may only be called during problem creation stage for an original constraint and variable.
18388  *
18389  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18390  */
18392  SCIP* scip, /**< SCIP data structure */
18393  SCIP_CONS* cons, /**< constraint data */
18394  SCIP_VAR* var /**< variable of constraint entry */
18395  )
18396 {
18397  assert(scip != NULL);
18398  assert(cons != NULL);
18399  assert(var != NULL);
18400 
18401  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18402 
18403  return SCIP_OKAY;
18404 }
18405 
18406 /** gets left hand side of linear constraint */
18408  SCIP* scip, /**< SCIP data structure */
18409  SCIP_CONS* cons /**< constraint data */
18410  )
18411 {
18412  SCIP_CONSDATA* consdata;
18413 
18414  assert(scip != NULL);
18415  assert(cons != NULL);
18416 
18417  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18418  {
18419  SCIPerrorMessage("constraint is not linear\n");
18420  SCIPABORT();
18421  return SCIP_INVALID; /*lint !e527*/
18422  }
18423 
18424  consdata = SCIPconsGetData(cons);
18425  assert(consdata != NULL);
18427  return consdata->lhs;
18428 }
18429 
18430 /** gets right hand side of linear constraint */
18432  SCIP* scip, /**< SCIP data structure */
18433  SCIP_CONS* cons /**< constraint data */
18434  )
18435 {
18436  SCIP_CONSDATA* consdata;
18437 
18438  assert(scip != NULL);
18439  assert(cons != NULL);
18440 
18441  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18442  {
18443  SCIPerrorMessage("constraint is not linear\n");
18444  SCIPABORT();
18445  return SCIP_INVALID; /*lint !e527*/
18446  }
18447 
18448  consdata = SCIPconsGetData(cons);
18449  assert(consdata != NULL);
18451  return consdata->rhs;
18452 }
18453 
18454 /** changes left hand side of linear constraint */
18456  SCIP* scip, /**< SCIP data structure */
18457  SCIP_CONS* cons, /**< constraint data */
18458  SCIP_Real lhs /**< new left hand side */
18459  )
18460 {
18461  assert(scip != NULL);
18462  assert(cons != NULL);
18463 
18464  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18465  {
18466  SCIPerrorMessage("constraint is not linear\n");
18467  return SCIP_INVALIDDATA;
18468  }
18469 
18470  SCIP_CALL( chgLhs(scip, cons, lhs) );
18471 
18472  return SCIP_OKAY;
18473 }
18475 /** changes right hand side of linear constraint */
18477  SCIP* scip, /**< SCIP data structure */
18478  SCIP_CONS* cons, /**< constraint data */
18479  SCIP_Real rhs /**< new right hand side */
18480  )
18481 {
18482  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18483  {
18484  SCIPerrorMessage("constraint is not linear\n");
18485  return SCIP_INVALIDDATA;
18486  }
18487 
18488  SCIP_CALL( chgRhs(scip, cons, rhs) );
18489 
18490  return SCIP_OKAY;
18491 }
18492 
18493 /** gets the number of variables in the linear constraint */
18494 int SCIPgetNVarsLinear(
18495  SCIP* scip, /**< SCIP data structure */
18496  SCIP_CONS* cons /**< constraint data */
18497  )
18498 {
18499  SCIP_CONSDATA* consdata;
18500 
18501  assert(scip != NULL);
18502  assert(cons != NULL);
18503 
18504  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18505  {
18506  SCIPerrorMessage("constraint is not linear\n");
18507  SCIPABORT();
18508  return -1; /*lint !e527*/
18509  }
18510 
18511  consdata = SCIPconsGetData(cons);
18512  assert(consdata != NULL);
18514  return consdata->nvars;
18515 }
18516 
18517 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18519  SCIP* scip, /**< SCIP data structure */
18520  SCIP_CONS* cons /**< constraint data */
18521  )
18522 {
18523  SCIP_CONSDATA* consdata;
18524 
18525  assert(scip != NULL);
18526  assert(cons != NULL);
18527 
18528  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18529  {
18530  SCIPerrorMessage("constraint is not linear\n");
18531  SCIPABORT();
18532  return NULL; /*lint !e527*/
18533  }
18534 
18535  consdata = SCIPconsGetData(cons);
18536  assert(consdata != NULL);
18538  return consdata->vars;
18539 }
18540 
18541 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18543  SCIP* scip, /**< SCIP data structure */
18544  SCIP_CONS* cons /**< constraint data */
18545  )
18546 {
18547  SCIP_CONSDATA* consdata;
18548 
18549  assert(scip != NULL);
18550  assert(cons != NULL);
18551 
18552  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18553  {
18554  SCIPerrorMessage("constraint is not linear\n");
18555  SCIPABORT();
18556  return NULL; /*lint !e527*/
18557  }
18558 
18559  consdata = SCIPconsGetData(cons);
18560  assert(consdata != NULL);
18562  return consdata->vals;
18563 }
18564 
18565 /** gets the activity of the linear constraint in the given solution
18566  *
18567  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18568  * comprises positive and negative infinity contributions
18569  */
18571  SCIP* scip, /**< SCIP data structure */
18572  SCIP_CONS* cons, /**< constraint data */
18573  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18574  )
18575 {
18576  SCIP_CONSDATA* consdata;
18577 
18578  assert(scip != NULL);
18579  assert(cons != NULL);
18580 
18581  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18582  {
18583  SCIPerrorMessage("constraint is not linear\n");
18584  SCIPABORT();
18585  return SCIP_INVALID; /*lint !e527*/
18586  }
18587 
18588  consdata = SCIPconsGetData(cons);
18589  assert(consdata != NULL);
18590 
18591  if( consdata->row != NULL )
18592  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18593  else
18594  return consdataGetActivity(scip, consdata, sol);
18595 }
18596 
18597 /** gets the feasibility of the linear constraint in the given solution */
18599  SCIP* scip, /**< SCIP data structure */
18600  SCIP_CONS* cons, /**< constraint data */
18601  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18602  )
18603 {
18604  SCIP_CONSDATA* consdata;
18605 
18606  assert(scip != NULL);
18607  assert(cons != NULL);
18608 
18609  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18610  {
18611  SCIPerrorMessage("constraint is not linear\n");
18612  SCIPABORT();
18613  return SCIP_INVALID; /*lint !e527*/
18614  }
18615 
18616  consdata = SCIPconsGetData(cons);
18617  assert(consdata != NULL);
18618 
18619  if( consdata->row != NULL )
18620  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18621  else
18622  return consdataGetFeasibility(scip, consdata, sol);
18623 }
18624 
18625 /** gets the dual solution of the linear constraint in the current LP */
18627  SCIP* scip, /**< SCIP data structure */
18628  SCIP_CONS* cons /**< constraint data */
18629  )
18630 {
18631  SCIP_CONSDATA* consdata;
18632 
18633  assert(scip != NULL);
18634  assert(cons != NULL);
18635  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18636 
18637  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18638  {
18639  SCIPerrorMessage("constraint is not linear\n");
18640  SCIPABORT();
18641  return SCIP_INVALID; /*lint !e527*/
18642  }
18643 
18644  consdata = SCIPconsGetData(cons);
18645  assert(consdata != NULL);
18646 
18647  if( consdata->row != NULL )
18648  return SCIProwGetDualsol(consdata->row);
18649  else
18650  return 0.0;
18651 }
18652 
18653 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18655  SCIP* scip, /**< SCIP data structure */
18656  SCIP_CONS* cons /**< constraint data */
18657  )
18658 {
18659  SCIP_CONSDATA* consdata;
18660 
18661  assert(scip != NULL);
18662  assert(cons != NULL);
18663  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18664 
18665  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18666  {
18667  SCIPerrorMessage("constraint is not linear\n");
18668  SCIPABORT();
18669  return SCIP_INVALID; /*lint !e527*/
18670  }
18671 
18672  consdata = SCIPconsGetData(cons);
18673  assert(consdata != NULL);
18674 
18675  if( consdata->row != NULL )
18676  return SCIProwGetDualfarkas(consdata->row);
18677  else
18678  return 0.0;
18679 }
18680 
18681 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18682  * the user must not modify the row!
18683  */
18685  SCIP* scip, /**< SCIP data structure */
18686  SCIP_CONS* cons /**< constraint data */
18687  )
18688 {
18689  SCIP_CONSDATA* consdata;
18690 
18691  assert(scip != NULL);
18692  assert(cons != NULL);
18693 
18694  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18695  {
18696  SCIPerrorMessage("constraint is not linear\n");
18697  SCIPABORT();
18698  return NULL; /*lint !e527*/
18699  }
18700 
18701  consdata = SCIPconsGetData(cons);
18702  assert(consdata != NULL);
18704  return consdata->row;
18705 }
18706 
18707 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18709  SCIP* scip, /**< SCIP data structure */
18710  SCIP_CONS* cons, /**< source constraint to try to convert */
18711  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18712  )
18713 {
18714  SCIP_CONSHDLR* conshdlr;
18715  SCIP_CONSHDLRDATA* conshdlrdata;
18716  SCIP_CONSDATA* consdata;
18717  SCIP_VAR* var;
18718  SCIP_Real val;
18719  SCIP_Real lb;
18720  SCIP_Real ub;
18721  SCIP_Real poscoeffsum;
18722  SCIP_Real negcoeffsum;
18723  SCIP_Bool infeasible;
18724  SCIP_Bool integral;
18725  int nchgsides = 0;
18726  int nposbin;
18727  int nnegbin;
18728  int nposint;
18729  int nnegint;
18730  int nposimpl;
18731  int nnegimpl;
18732  int nposimplbin;
18733  int nnegimplbin;
18734  int nposcont;
18735  int nnegcont;
18736  int ncoeffspone;
18737  int ncoeffsnone;
18738  int ncoeffspint;
18739  int ncoeffsnint;
18740  int ncoeffspfrac;
18741  int ncoeffsnfrac;
18742  int i;
18743 
18744  assert(scip != NULL);
18745  assert(cons != NULL);
18746  assert(upgdcons != NULL);
18747 
18748  *upgdcons = NULL;
18749 
18750  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18751  if( SCIPconsIsModifiable(cons) )
18752  return SCIP_OKAY;
18753 
18754  /* check for upgradability */
18755  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18756  return SCIP_OKAY;
18757 
18758  /* get the constraint handler and check, if it's really a linear constraint */
18759  conshdlr = SCIPconsGetHdlr(cons);
18760  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18761  {
18762  SCIPerrorMessage("constraint is not linear\n");
18763  return SCIP_INVALIDDATA;
18764  }
18765 
18766  /* get constraint handler data and constraint data */
18767  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18768  assert(conshdlrdata != NULL);
18769  consdata = SCIPconsGetData(cons);
18770  assert(consdata != NULL);
18771 
18772  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18773  if( consdata->upgraded )
18774  return SCIP_OKAY;
18775 
18776  /* check, if the constraint is already stored as LP row */
18777  if( consdata->row != NULL )
18778  {
18779  if( SCIProwIsInLP(consdata->row) )
18780  {
18781  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18782  return SCIP_INVALIDDATA;
18783  }
18784  else
18785  {
18786  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18787  }
18788  }
18789 
18790  /* normalize constraint */
18791  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18792 
18793  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18794  * skipped and we hope that the infeasibility gets detected later again.
18795  *
18796  * TODO: do we want to try to upgrade the constraint anyway?
18797  *
18798  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18799  * proven to be infeasible.
18800  */
18801  if( infeasible ) /*lint !e774*/
18802  return SCIP_OKAY;
18803 
18804  /* tighten sides */
18805  SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18806 
18807  if( infeasible ) /*lint !e774*/
18808  return SCIP_OKAY;
18809 
18810  /*
18811  * calculate some statistics on linear constraint
18812  */
18813 
18814  nposbin = 0;
18815  nnegbin = 0;
18816  nposint = 0;
18817  nnegint = 0;
18818  nposimpl = 0;
18819  nnegimpl = 0;
18820  nposimplbin = 0;
18821  nnegimplbin = 0;
18822  nposcont = 0;
18823  nnegcont = 0;
18824  ncoeffspone = 0;
18825  ncoeffsnone = 0;
18826  ncoeffspint = 0;
18827  ncoeffsnint = 0;
18828  ncoeffspfrac = 0;
18829  ncoeffsnfrac = 0;
18830  integral = TRUE;
18831  poscoeffsum = 0.0;
18832  negcoeffsum = 0.0;
18833 
18834  for( i = 0; i < consdata->nvars; ++i )
18835  {
18836  var = consdata->vars[i];
18837  val = consdata->vals[i];
18838  lb = SCIPvarGetLbLocal(var);
18839  ub = SCIPvarGetUbLocal(var);
18840  assert(!SCIPisZero(scip, val));
18841 
18842  switch( SCIPvarGetType(var) )
18843  {
18844  case SCIP_VARTYPE_BINARY:
18845  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18846  integral = integral && SCIPisIntegral(scip, val);
18847  if( val >= 0.0 )
18848  nposbin++;
18849  else
18850  nnegbin++;
18851  break;
18852  case SCIP_VARTYPE_INTEGER:
18853  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18854  integral = integral && SCIPisIntegral(scip, val);
18855  if( val >= 0.0 )
18856  nposint++;
18857  else
18858  nnegint++;
18859  break;
18860  case SCIP_VARTYPE_IMPLINT:
18861  if( SCIPvarIsBinary(var) )
18862  {
18863  if( val >= 0.0 )
18864  nposimplbin++;
18865  else
18866  nnegimplbin++;
18867  }
18868  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18869  integral = integral && SCIPisIntegral(scip, val);
18870  if( val >= 0.0 )
18871  nposimpl++;
18872  else
18873  nnegimpl++;
18874  break;
18876  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18877  if( val >= 0.0 )
18878  nposcont++;
18879  else
18880  nnegcont++;
18881  break;
18882  default:
18883  SCIPerrorMessage("unknown variable type\n");
18884  return SCIP_INVALIDDATA;
18885  }
18886  if( SCIPisEQ(scip, val, 1.0) )
18887  ncoeffspone++;
18888  else if( SCIPisEQ(scip, val, -1.0) )
18889  ncoeffsnone++;
18890  else if( SCIPisIntegral(scip, val) )
18891  {
18892  if( SCIPisPositive(scip, val) )
18893  ncoeffspint++;
18894  else
18895  ncoeffsnint++;
18896  }
18897  else
18898  {
18899  if( SCIPisPositive(scip, val) )
18900  ncoeffspfrac++;
18901  else
18902  ncoeffsnfrac++;
18903  }
18904  if( SCIPisPositive(scip, val) )
18905  poscoeffsum += val;
18906  else
18907  negcoeffsum += val;
18908  }
18909 
18910  /*
18911  * call the upgrading methods
18912  */
18913 
18914  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18915  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18916  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",
18917  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18918  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18919  poscoeffsum, negcoeffsum, integral);
18920 
18921  /* try all upgrading methods in priority order in case the upgrading step is enable */
18922  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18923  {
18924  if( conshdlrdata->linconsupgrades[i]->active )
18925  {
18926  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18927  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18928  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18929  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18930  poscoeffsum, negcoeffsum, integral,
18931  upgdcons) );
18932  }
18933  }
18934 
18935 #ifdef SCIP_DEBUG
18936  if( *upgdcons != NULL )
18937  {
18938  SCIPdebugPrintCons(scip, cons, NULL);
18939  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18940  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18941  }
18942 #endif
18943 
18944  return SCIP_OKAY; /*lint !e438*/
18945 }
18946 
18947 /** cleans up (multi-)aggregations and fixings from linear constraints */
18949  SCIP* scip, /**< SCIP data structure */
18950  SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18951  SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18952  )
18953 {
18954  SCIP_CONSHDLR* conshdlr;
18955  SCIP_CONS** conss;
18956  int nconss;
18957  int i;
18958 
18959  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18960  if( conshdlr == NULL )
18961  return SCIP_OKAY;
18962 
18963  assert(infeasible != NULL);
18964  *infeasible = FALSE;
18965 
18966  nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18967  conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18968 
18969  for( i = 0; i < nconss; ++i )
18970  {
18971  SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18972 
18973  if( *infeasible )
18974  break;
18975  }
18976 
18977  return SCIP_OKAY;
18978 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define EVENTHDLR_DESC
Definition: cons_linear.c:109
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:101
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:101
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:111
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4205
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1721
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1413
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:90
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1690
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:81
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:563
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:137
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6824
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1458
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
Definition: cons_linear.c:867
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:418
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:731
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:84
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:4029
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:101
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5200
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3171
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2125
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for SCIP parameter handling
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3289
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:132
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:356
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:120
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:63
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8344
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17702
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:586
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_NAME
Definition: cons_linear.c:90
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1989
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:100
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:3192
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2487
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:1625
public methods for memory management
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:167
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1563
#define MAXSCALEDCOEF
Definition: cons_linear.c:177
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:345
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:877
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:129
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3798
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7895
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18512
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:116
#define DEFAULT_SORTVARS
Definition: cons_linear.c:126
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9555
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:5436
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17910
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:816
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)
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
#define SCIP_MAXSTRLEN
Definition: def.h:293
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3347
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17452
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
public methods for conflict handler plugins and conflict analysis
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:308
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1749
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:836
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:7979
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2842
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:130
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17690
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1686
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1308
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2083
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17966
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1172
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:678
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition: event.c:1274
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:95
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2312
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:521
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
static SCIP_DECL_CONSINITSOL(consInitsolLinear)
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:118
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1436
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1461
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1245
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17431
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1326
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4260
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:77
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:161
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2054
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#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:2889
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3346
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4547
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:144
#define FALSE
Definition: def.h:87
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4642
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1227
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8095
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:315
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11063
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:166
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
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:2951
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:602
#define TRUE
Definition: def.h:86
#define SCIPdebug(x)
Definition: pub_message.h:84
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:138
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1979
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3584
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17747
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:122
#define SCIPstatisticMessage
Definition: pub_message.h:114
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8364
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
Definition: cons_linear.c:7657
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17600
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:66
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:7947
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17654
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8394
public methods for problem variables
static GRAPHNODE ** active
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5317
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:99
#define SCIPdebugMessage
Definition: pub_message.h:87
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:123
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:220
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9719
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8444
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:79
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:123
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3087
enum Proprule PROPRULE
Definition: cons_linear.c:368
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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:127
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:427
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5839
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4610
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17462
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:93
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:566
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:419
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:770
public methods for SCIP variables
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:747
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1558
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17736
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8354
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:116
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3237
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:609
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17278
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:111
#define SCIPdebugMsgPrint
Definition: scip_message.h:70
#define SCIPdebugMsg
Definition: scip_message.h:69
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:74
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2328
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1477
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:793
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:141
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8146
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8999
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:119
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2171
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:5106
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:934
SCIP_Real SCIPepsilon(SCIP *scip)
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:700
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:105
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:106
public methods for numerical tolerances
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2236
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8384
public functions to work with algebraic expressions
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:112
public methods for querying solving statistics
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:95
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17726
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17489
#define MAXCONSPRESOLROUNDS
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4256
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
public methods for the branch-and-bound tree
static SCIP_DECL_EVENTEXEC(eventExecLinear)
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9295
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:542
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1233
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8173
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5315
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:7274
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:6918
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3808
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17920
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:429
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:96
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:111
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:8532
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:151
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1233
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:603
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1863
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8424
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:113
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:332
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1157
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:5367
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:2509
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPerrorMessage
Definition: pub_message.h:55
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4175
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1257
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2769
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:96
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3392
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:354
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8595
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3473
public methods for event handler plugins and event handlers
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:5429
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:407
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1016
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1791
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1434
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:6777
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:535
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:169
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3615
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:461
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:48
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2156
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3422
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4434
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2106
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:409
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9121
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8085
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17666
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8304
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:164
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17251
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:357
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4195
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5171
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1951
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3908
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:5222
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:446
#define SCIPhashSeven(a, b, c, d, e, f, g)
Definition: pub_misc.h:526
#define REALABS(x)
Definition: def.h:201
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:260
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:632
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:102
public methods for problem copies
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8434
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5094
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1443
#define SCIP_CALL(x)
Definition: def.h:384
SCIP_Real SCIPgetLowerbound(SCIP *scip)
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:68
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2608
enum Proprule PROPRULE
Definition: cons_and.c:169
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:94
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5505
#define SCIPhashSignature64(a)
Definition: pub_misc.h:508
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:1735
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17714
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17538
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2617
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:276
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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:2408
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:216
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
Definition: graph_load.c:93
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8324
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4108
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:241
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:632
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:281
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:56
static SCIP_DECL_CONSTRANS(consTransLinear)
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17377
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:114
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:74
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:113
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4590
public methods for constraint handler plugins and constraints
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:7747
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2213
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:156
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4510
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1116
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17380
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2744
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3489
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1044
#define SCIP_Bool
Definition: def.h:84
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1598
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:103
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:97
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1021
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4201
static const char * paramname[]
Definition: lpi_msk.c:5031
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1407
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3103
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:661
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:7092
constraint handler for nonlinear constraints specified by algebraic expressions
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:580
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:148
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2473
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:146
#define MAX(x, y)
Definition: tclique_def.h:83
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4593
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7558
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8105
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11941
methods for debugging
public methods for LP management
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2519
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1574
public methods for cuts and aggregation rows
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8284
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2060
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8254
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17758
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1273
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:391
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18502
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2346
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:193
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17642
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:105
static int getVarWeight(SCIP_VAR *var)
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:912
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8273
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:127
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17291
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4348
#define MAXDNOM
Definition: cons_linear.c:176
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:770
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:70
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2219
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2548
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17678
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2129
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:117
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:111
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12773
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5498
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:115
#define SCIP_MAXTREEDEPTH
Definition: def.h:320
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2036
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4624
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:88
public methods for the LP relaxation, rows and columns
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:145
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7534
#define MINVALRECOMP
Definition: cons_linear.c:190
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2286
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:92
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1991
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8536
#define SCIP_REAL_MAX
Definition: def.h:178
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:382
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2657
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1353
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:334
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3695
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
Definition: cons_linear.c:5339
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:178
static SCIP_DECL_CONSACTIVE(consActiveLinear)
methods for sorting joint arrays of various types
static SCIP_DECL_CONSCHECK(consCheckLinear)
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8478
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:501
#define EPSGT(x, y, eps)
Definition: def.h:205
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:556
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:3217
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1553
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:5781
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:664
general public methods
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5440
SCIP_Bool SCIPisGT(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:2738
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
public methods for solutions
static const SCIP_Real scalars[]
Definition: lp.c:5738
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:702
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1667
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8115
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:5612
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:381
#define CONTWEIGHT
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4567
SCIP_Real SCIPgetHugeValue(SCIP *scip)
static SCIP_DECL_CONSLOCK(consLockLinear)
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip_cons.c:1258
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1487
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:804
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:405
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:143
public methods for conflict analysis handlers
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3041
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:8030
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:651
public methods for the probing mode
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
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:99
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:763
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:525
public methods for message output
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1209
SCIP_VAR * a
Definition: circlepacking.c:57
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1421
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:609
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9611
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1946
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:112
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17370
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:8398
#define DEFAULT_MAXDUALMULTAGGRQUOT
Definition: cons_linear.c:173
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1211
#define SCIP_Real
Definition: def.h:177
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7096
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8334
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1712
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:694
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:64
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9669
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:147
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:839
#define EVENTHDLR_NAME
Definition: cons_linear.c:108
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:93
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4664
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4610
public methods for message handling
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1155
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8274
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8562
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define SCIP_INVALID
Definition: def.h:197
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:164
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8264
Proprule
Definition: cons_and.c:161
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2197
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3743
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:91
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
#define SCIP_Longint
Definition: def.h:162
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18022
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17590
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2152
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:486
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:280
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17416
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7963
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1380
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9723
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:55
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17976
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:102
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17393
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:400
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8294
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define MAXVALRECOMP
Definition: cons_linear.c:189
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:697
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:123
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:655
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:135
SCIPallocBlockMemory(scip, subsol))
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:430
#define DEFAULT_EXTRACTCLIQUES
Definition: cons_linear.c:174
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:67
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3227
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
#define SCIP_CALL_ABORT(x)
Definition: def.h:363
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
static SCIP_DECL_CONSEXIT(consExitLinear)
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:166
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:453
#define SCIPABORT()
Definition: def.h:356
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:221
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17442
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9022
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1352
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17472
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:387
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1267
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define MAXACTVAL
Definition: cons_linear.c:183
#define INTWEIGHT
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8626
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:130
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4924
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9274
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7621
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:62
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:2010
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
#define DEFAULT_MAXMULTAGGRQUOT
Definition: cons_linear.c:172
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:48
int SCIPgetNSepaRounds(SCIP *scip)
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:121
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17580
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17406
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:2035
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1075
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:142
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:119
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:266
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1208
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:115
memory allocation routines
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:165