Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Michael Winkler
23  * @author Gerald Gamrath
24  * @author Domenico Salvagnin
25  *
26  * Linear constraints are separated with a high priority, because they are easy
27  * to separate. Instead of using the global cut pool, the same effect can be
28  * implemented by adding linear constraints to the root node, such that they are
29  * separated each time, the linear constraints are separated. A constraint
30  * handler, which generates linear constraints in this way should have a lower
31  * separation priority than the linear constraint handler, and it should have a
32  * separation frequency that is a multiple of the frequency of the linear
33  * constraint handler. In this way, it can be avoided to separate the same cut
34  * twice, because if a separation run of the handler is always preceded by a
35  * separation of the linear constraints, the priorily added constraints are
36  * always satisfied.
37  *
38  * Linear constraints are enforced and checked with a very low priority. Checking
39  * of (many) linear constraints is much more involved than checking the solution
40  * values for integrality. Because we are separating the linear constraints quite
41  * often, it is only necessary to enforce them for integral solutions. A constraint
42  * handler which generates pool cuts in its enforcing method should have an
43  * enforcing priority smaller than that of the linear constraint handler to avoid
44  * regenerating constraints which already exist.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include "blockmemshell/memory.h"
50 #include "scip/cons_knapsack.h"
51 #include "scip/cons_linear.h"
52 #include "scip/cons_nonlinear.h"
53 #include "scip/cons_quadratic.h"
54 #include "scip/debug.h"
55 #include "scip/pub_conflict.h"
56 #include "scip/pub_cons.h"
57 #include "scip/pub_event.h"
58 #include "scip/pub_lp.h"
59 #include "scip/pub_message.h"
60 #include "scip/pub_misc.h"
61 #include "scip/pub_misc_sort.h"
62 #include "scip/pub_var.h"
63 #include "scip/scip_branch.h"
64 #include "scip/scip_conflict.h"
65 #include "scip/scip_cons.h"
66 #include "scip/scip_copy.h"
67 #include "scip/scip_cut.h"
68 #include "scip/scip_event.h"
69 #include "scip/scip_general.h"
70 #include "scip/scip_lp.h"
71 #include "scip/scip_mem.h"
72 #include "scip/scip_message.h"
73 #include "scip/scip_numerics.h"
74 #include "scip/scip_param.h"
75 #include "scip/scip_prob.h"
76 #include "scip/scip_probing.h"
77 #include "scip/scip_sol.h"
78 #include "scip/scip_solvingstats.h"
79 #include "scip/scip_tree.h"
80 #include "scip/scip_var.h"
81 #include <ctype.h>
82 #include <string.h>
83 #if defined(_WIN32) || defined(_WIN64)
84 #else
85 #include <strings.h> /*lint --e{766}*/
86 #endif
87 
88 
89 #define CONSHDLR_NAME "linear"
90 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
91 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
92 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
93 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
94 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
95 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
96 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
97  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
98 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
99 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
100 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
101 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
103 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
104 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
106 #define EVENTHDLR_NAME "linear"
107 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
109 #define CONFLICTHDLR_NAME "linear"
110 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
111 #define CONFLICTHDLR_PRIORITY -1000000
113 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
114 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
115 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
116 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
117 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
118 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
119 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
120 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
121 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
122  * comparison round */
123 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
124  * propagation? */
125 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
126  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
127 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
128  * (0.0: disable constraint aggregation) */
129 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
130  * (faster, but numerically less stable) */
131 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
132  * to best node's dual bound for separating knapsack cardinality cuts */
133 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
134  * the ones with non-zero dual value? */
135 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
136 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
137 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
138 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
139 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
140  * constraints using the cheapest variable? */
141 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
142  * function defining an upper bound and prevent these constraints from
143  * entering the LP */
144 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
145  * function defining a lower bound and prevent these constraints from
146  * entering the LP */
147 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
148  * objective function */
149 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
150 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
151 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
152 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
153 
154 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
155  * removed afterwards? */
156 
157 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
158 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
159 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
160  * type
161  */
162 
163 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
164 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
167 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
168 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
169 
170 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
171  * maybe in fullDualPresolve(), see convertLongEquality()
172  */
175 /** constraint data for linear constraints */
176 struct SCIP_ConsData
177 {
178  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
179  SCIP_Real rhs; /**< right hand side of row */
180  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
181  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
182  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
183  * activity, ignoring the coefficients contributing with infinite value */
184  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
185  * activity, ignoring the coefficients contributing with infinite value */
186  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
187  * over all contributing values */
188  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
189  * over all contributing values */
190  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
191  * activity, ignoring the coefficients contributing with infinite value */
192  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
193  * activity, ignoring the coefficients contributing with infinite value */
194  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
195  * over all contributing values */
196  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
197  * over all contributing values */
198  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
199  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
200  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
201  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
202  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
203  SCIP_VAR** vars; /**< variables of constraint entries */
204  SCIP_Real* vals; /**< coefficients of constraint entries */
205  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
206  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
207  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
208  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
209  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
210  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
211  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
212  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
213  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
214  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
215  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
216  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
217  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
218  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
219  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
220  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
221  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
222  int varssize; /**< size of the vars- and vals-arrays */
223  int nvars; /**< number of nonzeros in constraint */
224  int nbinvars; /**< the number of binary variables in the constraint, only valid after
225  * sorting in stage >= SCIP_STAGE_INITSOLVE
226  */
227  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
228  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
229  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
230  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
231  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
232  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
233  unsigned int validminact:1; /**< is the local minactivity valid? */
234  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
235  unsigned int validglbminact:1; /**< is the global minactivity valid? */
236  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
237  unsigned int presolved:1; /**< is constraint already presolved? */
238  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
239  unsigned int validsignature:1; /**< is the bit signature valid? */
240  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
241  unsigned int normalized:1; /**< is the constraint in normalized form? */
242  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
243  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
244  unsigned int sorted:1; /**< are the constraint's variables sorted? */
245  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
246  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
247  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
248  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
249  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
250  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
251  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
252  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
253  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
254 };
255 
256 /** event data for bound change event */
257 struct SCIP_EventData
258 {
259  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
260  int varpos; /**< position of variable in vars array */
261  int filterpos; /**< position of event in variable's event filter */
262 };
263 
264 /** constraint handler data */
265 struct SCIP_ConshdlrData
266 {
267  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
268  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
269  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
270  * (0.0: disable constraint aggregation) */
271  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
272  * to best node's dual bound for separating knapsack cardinality cuts */
273  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
274  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
275  * (faster, but numerically less stable) */
276  int linconsupgradessize;/**< size of linconsupgrade array */
277  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
278  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
279  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
280  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
281  int maxsepacuts; /**< maximal number of cuts separated per separation round */
282  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
283  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
284  int naddconss; /**< number of added constraints */
285  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
286  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
287  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
288  * the ones with non-zero dual value? */
289  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
290  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
291  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
292  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
293  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
294  * constraints using the cheapest variable? */
295  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
296  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
297  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
298  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
299  * function defining an upper bound and prevent these constraints from
300  * entering the LP */
301  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
302  * function defining a lower bound and prevent these constraints from
303  * entering the LP */
304  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
305  * the objective function */
306  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
307  * infeasibility, and extract sub-constraints from ranged rows and
308  * equations */
309  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
310  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
311  int rangedrowfreq; /**< frequency for applying ranged row propagation */
312  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
313  * removed afterwards? */
314 };
315 
316 /** linear constraint update method */
317 struct SCIP_LinConsUpgrade
318 {
319  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
320  int priority; /**< priority of upgrading method */
321  SCIP_Bool active; /**< is upgrading enabled */
322 };
323 
324 
325 /*
326  * Propagation rules
327  */
328 
329 enum Proprule
330 {
331  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
332  * variable due to the right hand side of the inequality */
333  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
334  * variable due to the left hand side of the inequality */
335  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
336  * single variable in this reanged row */
337  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
338 };
339 typedef enum Proprule PROPRULE;
340 
341 /** inference information */
342 struct InferInfo
343 {
344  union
345  {
346  struct
347  {
348  unsigned int proprule:8; /**< propagation rule that was applied */
349  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
350  } asbits;
351  int asint; /**< inference information as a single int value */
352  } val;
353 };
354 typedef struct InferInfo INFERINFO;
355 
356 /** converts an integer into an inference information */
357 static
359  int i /**< integer to convert */
360  )
361 {
362  INFERINFO inferinfo;
363 
364  inferinfo.val.asint = i;
365 
366  return inferinfo;
367 }
368 
369 /** converts an inference information into an int */
370 static
372  INFERINFO inferinfo /**< inference information to convert */
373  )
374 {
375  return inferinfo.val.asint;
376 }
377 
378 /** returns the propagation rule stored in the inference information */
379 static
381  INFERINFO inferinfo /**< inference information to convert */
382  )
383 {
384  return (int) inferinfo.val.asbits.proprule;
385 }
386 
387 /** returns the position stored in the inference information */
388 static
389 int inferInfoGetPos(
390  INFERINFO inferinfo /**< inference information to convert */
391  )
392 {
393  return (int) inferinfo.val.asbits.pos;
394 }
395 
396 /** constructs an inference information out of a propagation rule and a position number */
397 static
399  PROPRULE proprule, /**< propagation rule that deduced the value */
400  int pos /**< variable position, the propagation rule was applied at */
401  )
402 {
403  INFERINFO inferinfo;
404 
405  assert(pos >= 0);
406  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
407  assert(pos < (1<<24));
408 
409  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
410  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
411 
412  return inferinfo;
413 }
414 
415 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
416 static
417 int getInferInt(
418  PROPRULE proprule, /**< propagation rule that deduced the value */
419  int pos /**< variable position, the propagation rule was applied at */
420  )
421 {
422  return inferInfoToInt(getInferInfo(proprule, pos));
423 }
424 
425 
426 /*
427  * memory growing methods for dynamically allocated arrays
428  */
429 
430 /** ensures, that linconsupgrades array can store at least num entries */
431 static
433  SCIP* scip, /**< SCIP data structure */
434  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
435  int num /**< minimum number of entries to store */
436  )
437 {
438  assert(scip != NULL);
439  assert(conshdlrdata != NULL);
440  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
441 
442  if( num > conshdlrdata->linconsupgradessize )
443  {
444  int newsize;
445 
446  newsize = SCIPcalcMemGrowSize(scip, num);
447  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
448  conshdlrdata->linconsupgradessize = newsize;
449  }
450  assert(num <= conshdlrdata->linconsupgradessize);
451 
452  return SCIP_OKAY;
453 }
454 
455 /** ensures, that vars and vals arrays can store at least num entries */
456 static
458  SCIP* scip, /**< SCIP data structure */
459  SCIP_CONSDATA* consdata, /**< linear constraint data */
460  int num /**< minimum number of entries to store */
461  )
462 {
463  assert(scip != NULL);
464  assert(consdata != NULL);
465  assert(consdata->nvars <= consdata->varssize);
466 
467  if( num > consdata->varssize )
468  {
469  int newsize;
470 
471  newsize = SCIPcalcMemGrowSize(scip, num);
472  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
473  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
474  if( consdata->eventdata != NULL )
475  {
476  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
477  }
478  consdata->varssize = newsize;
479  }
480  assert(num <= consdata->varssize);
481 
482  return SCIP_OKAY;
483 }
484 
485 
486 /*
487  * local methods for managing linear constraint update methods
488  */
489 
490 /** creates a linear constraint upgrade data object */
491 static
493  SCIP* scip, /**< SCIP data structure */
494  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
495  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
496  int priority /**< priority of upgrading method */
497  )
498 {
499  assert(scip != NULL);
500  assert(linconsupgrade != NULL);
501  assert(linconsupgd != NULL);
502 
503  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
504  (*linconsupgrade)->linconsupgd = linconsupgd;
505  (*linconsupgrade)->priority = priority;
506  (*linconsupgrade)->active = TRUE;
507 
508  return SCIP_OKAY;
509 }
510 
511 /** frees a linear constraint upgrade data object */
512 static
513 void linconsupgradeFree(
514  SCIP* scip, /**< SCIP data structure */
515  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
516  )
517 {
518  assert(scip != NULL);
519  assert(linconsupgrade != NULL);
520  assert(*linconsupgrade != NULL);
521 
522  SCIPfreeBlockMemory(scip, linconsupgrade);
523 }
524 
525 /** creates constraint handler data for linear constraint handler */
526 static
528  SCIP* scip, /**< SCIP data structure */
529  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
530  SCIP_EVENTHDLR* eventhdlr /**< event handler */
531  )
532 {
533  assert(scip != NULL);
534  assert(conshdlrdata != NULL);
535  assert(eventhdlr != NULL);
536 
537  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
538  (*conshdlrdata)->linconsupgrades = NULL;
539  (*conshdlrdata)->linconsupgradessize = 0;
540  (*conshdlrdata)->nlinconsupgrades = 0;
541  (*conshdlrdata)->naddconss = 0;
542 
543  /* set event handler for updating linear constraint activity bounds */
544  (*conshdlrdata)->eventhdlr = eventhdlr;
545 
546  return SCIP_OKAY;
547 }
548 
549 /** frees constraint handler data for linear constraint handler */
550 static
551 void conshdlrdataFree(
552  SCIP* scip, /**< SCIP data structure */
553  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
554  )
555 {
556  int i;
557 
558  assert(scip != NULL);
559  assert(conshdlrdata != NULL);
560  assert(*conshdlrdata != NULL);
561 
562  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
563  {
564  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
565  }
566  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
567 
568  SCIPfreeBlockMemory(scip, conshdlrdata);
569 }
570 
571 /** creates a linear constraint upgrade data object */
572 static
574  SCIP* scip, /**< SCIP data structure */
575  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
576  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
577  const char* conshdlrname /**< name of the constraint handler */
578  )
579 {
580  int i;
581 
582  assert(scip != NULL);
583  assert(conshdlrdata != NULL);
584  assert(linconsupgd != NULL);
585  assert(conshdlrname != NULL);
586 
587  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
588  {
589  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
590  {
591 #ifdef SCIP_DEBUG
592  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
593 #endif
594  return TRUE;
595  }
596  }
597 
598  return FALSE;
599 }
600 
601 /** adds a linear constraint update method to the constraint handler's data */
602 static
604  SCIP* scip, /**< SCIP data structure */
605  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
606  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
607  )
608 {
609  int i;
610 
611  assert(scip != NULL);
612  assert(conshdlrdata != NULL);
613  assert(linconsupgrade != NULL);
614 
615  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
616 
617  for( i = conshdlrdata->nlinconsupgrades;
618  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
619  {
620  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
621  }
622  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
623  conshdlrdata->linconsupgrades[i] = linconsupgrade;
624  conshdlrdata->nlinconsupgrades++;
625 
626  return SCIP_OKAY;
627 }
628 
629 /*
630  * local methods
631  */
632 
633 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
634 static
636  SCIP* scip, /**< SCIP data structure */
637  SCIP_CONS* cons, /**< linear constraint */
638  SCIP_VAR* var, /**< variable of constraint entry */
639  SCIP_Real val /**< coefficient of constraint entry */
640  )
641 {
642  SCIP_CONSDATA* consdata;
643 
644  assert(scip != NULL);
645  assert(cons != NULL);
646  assert(var != NULL);
647 
648  consdata = SCIPconsGetData(cons);
649  assert(consdata != NULL);
650  assert(!SCIPisZero(scip, val));
651 
652  if( SCIPisPositive(scip, val) )
653  {
654  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
655  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
656  }
657  else
658  {
659  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
660  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
661  }
662 
663  return SCIP_OKAY;
664 }
665 
666 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
667 static
669  SCIP* scip, /**< SCIP data structure */
670  SCIP_CONS* cons, /**< linear constraint */
671  SCIP_VAR* var, /**< variable of constraint entry */
672  SCIP_Real val /**< coefficient of constraint entry */
673  )
674 {
675  SCIP_CONSDATA* consdata;
676 
677  assert(scip != NULL);
678  assert(cons != NULL);
679  assert(var != NULL);
680 
681  consdata = SCIPconsGetData(cons);
682  assert(consdata != NULL);
683  assert(!SCIPisZero(scip, val));
684 
685  if( SCIPisPositive(scip, val) )
686  {
687  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
688  !SCIPisInfinity(scip, consdata->rhs)) );
689  }
690  else
691  {
692  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
693  !SCIPisInfinity(scip, -consdata->lhs)) );
694  }
695 
696  return SCIP_OKAY;
697 }
698 
699 /** creates event data for variable at given position, and catches events */
700 /**! [SnippetDebugAssertions] */
701 static
703  SCIP* scip, /**< SCIP data structure */
704  SCIP_CONS* cons, /**< linear constraint */
705  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
706  int pos /**< array position of variable to catch bound change events for */
707  )
708 {
709  SCIP_CONSDATA* consdata;
710  assert(scip != NULL);
711  assert(cons != NULL);
712  assert(eventhdlr != NULL);
713 
714  consdata = SCIPconsGetData(cons);
715  assert(consdata != NULL);
716 
717  assert(0 <= pos && pos < consdata->nvars);
718  assert(consdata->vars != NULL);
719  assert(consdata->vars[pos] != NULL);
720  assert(SCIPvarIsTransformed(consdata->vars[pos]));
721  assert(consdata->eventdata != NULL);
722  assert(consdata->eventdata[pos] == NULL);
723 
724  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
725  consdata->eventdata[pos]->cons = cons;
726  consdata->eventdata[pos]->varpos = pos;
727 
728  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
731  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
732 
733  return SCIP_OKAY;
734 }
735 /**! [SnippetDebugAssertions] */
736 
737 /** deletes event data for variable at given position, and drops events */
738 static
740  SCIP* scip, /**< SCIP data structure */
741  SCIP_CONS* cons, /**< linear constraint */
742  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
743  int pos /**< array position of variable to catch bound change events for */
744  )
745 {
746  SCIP_CONSDATA* consdata;
747  assert(scip != NULL);
748  assert(cons != NULL);
749  assert(eventhdlr != NULL);
750 
751  consdata = SCIPconsGetData(cons);
752  assert(consdata != NULL);
753 
754  assert(0 <= pos && pos < consdata->nvars);
755  assert(consdata->vars[pos] != NULL);
756  assert(consdata->eventdata != NULL);
757  assert(consdata->eventdata[pos] != NULL);
758  assert(consdata->eventdata[pos]->cons == cons);
759  assert(consdata->eventdata[pos]->varpos == pos);
760 
761  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
764  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
765 
766  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
767 
768  return SCIP_OKAY;
769 }
770 
771 /** catches bound change events for all variables in transformed linear constraint */
772 static
774  SCIP* scip, /**< SCIP data structure */
775  SCIP_CONS* cons, /**< linear constraint */
776  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
777  )
778 {
779  SCIP_CONSDATA* consdata;
780  int i;
781 
782  assert(scip != NULL);
783  assert(cons != NULL);
784 
785  consdata = SCIPconsGetData(cons);
786  assert(consdata != NULL);
787  assert(consdata->eventdata == NULL);
788 
789  /* allocate eventdata array */
790  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
791  assert(consdata->eventdata != NULL);
792  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
793 
794  /* catch event for every single variable */
795  for( i = 0; i < consdata->nvars; ++i )
796  {
797  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
798  }
799 
800  return SCIP_OKAY;
801 }
802 
803 /** drops bound change events for all variables in transformed linear constraint */
804 static
806  SCIP* scip, /**< SCIP data structure */
807  SCIP_CONS* cons, /**< linear constraint */
808  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
809  )
810 {
811  SCIP_CONSDATA* consdata;
812  int i;
813 
814  assert(scip != NULL);
815  assert(cons != NULL);
816 
817  consdata = SCIPconsGetData(cons);
818  assert(consdata != NULL);
819  assert(consdata->eventdata != NULL);
820 
821  /* drop event of every single variable */
822  for( i = consdata->nvars - 1; i >= 0; --i )
823  {
824  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
825  }
826 
827  /* free eventdata array */
828  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
829  assert(consdata->eventdata == NULL);
830 
831  return SCIP_OKAY;
832 }
833 
834 /** creates a linear constraint data */
835 static
837  SCIP* scip, /**< SCIP data structure */
838  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
839  int nvars, /**< number of nonzeros in the constraint */
840  SCIP_VAR** vars, /**< array with variables of constraint entries */
841  SCIP_Real* vals, /**< array with coefficients of constraint entries */
842  SCIP_Real lhs, /**< left hand side of row */
843  SCIP_Real rhs /**< right hand side of row */
844  )
845 {
846  int v;
847  SCIP_Real constant;
848 
849  assert(scip != NULL);
850  assert(consdata != NULL);
851  assert(nvars == 0 || vars != NULL);
852  assert(nvars == 0 || vals != NULL);
854  if( SCIPisInfinity(scip, rhs) )
855  rhs = SCIPinfinity(scip);
856  else if( SCIPisInfinity(scip, -rhs) )
857  rhs = -SCIPinfinity(scip);
858 
859  if( SCIPisInfinity(scip, -lhs) )
860  lhs = -SCIPinfinity(scip);
861  else if( SCIPisInfinity(scip, lhs) )
862  lhs = SCIPinfinity(scip);
863 
864  if( SCIPisGT(scip, lhs, rhs) )
865  {
866  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
867  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
868  }
869 
870  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
871 
872  (*consdata)->varssize = 0;
873  (*consdata)->nvars = nvars;
874  (*consdata)->hascontvar = FALSE;
875  (*consdata)->hasnonbinvar = FALSE;
876  (*consdata)->hasnonbinvalid = TRUE;
877  (*consdata)->vars = NULL;
878  (*consdata)->vals = NULL;
879 
880  constant = 0.0;
881  if( nvars > 0 )
882  {
883  int k;
884 
885  SCIP_VAR** varsbuffer;
886  SCIP_Real* valsbuffer;
887 
888  /* copy variables into temporary buffer */
889  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
890  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
891  k = 0;
892 
893  /* loop over variables and sort out fixed ones */
894  for( v = 0; v < nvars; ++v )
895  {
896  SCIP_VAR* var;
897  SCIP_Real val;
898 
899  var = vars[v];
900  val = vals[v];
901 
902  assert(var != NULL);
903  if( !SCIPisZero(scip, val) )
904  {
905  /* treat fixed variable as a constant if problem compression is enabled */
907  {
908  constant += SCIPvarGetLbGlobal(var) * val;
909  }
910  else
911  {
912  varsbuffer[k] = var;
913  valsbuffer[k] = val;
914  k++;
915 
916  /* update hascontvar and hasnonbinvar flags */
917  if( !(*consdata)->hascontvar )
918  {
919  SCIP_VARTYPE vartype = SCIPvarGetType(var);
920 
921  if( vartype != SCIP_VARTYPE_BINARY )
922  {
923  (*consdata)->hasnonbinvar = TRUE;
924 
925  if( vartype == SCIP_VARTYPE_CONTINUOUS )
926  (*consdata)->hascontvar = TRUE;
927  }
928  }
929  }
930  }
931  }
932  (*consdata)->nvars = k;
933 
934  if( k > 0 )
935  {
936  /* copy the possibly reduced buffer arrays into block */
937  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
938  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
939  (*consdata)->varssize = k;
940  }
941  /* free temporary buffer */
942  SCIPfreeBufferArray(scip, &valsbuffer);
943  SCIPfreeBufferArray(scip, &varsbuffer);
944  }
945 
946  (*consdata)->eventdata = NULL;
947 
948  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
949  if( !SCIPisZero(scip, constant) )
950  {
951  if( !SCIPisInfinity(scip, REALABS(lhs)) )
952  lhs -= constant;
953 
954  if( !SCIPisInfinity(scip, REALABS(rhs)) )
955  rhs -= constant;
956  }
957 
958  (*consdata)->row = NULL;
959  (*consdata)->lhs = lhs;
960  (*consdata)->rhs = rhs;
961  (*consdata)->maxabsval = SCIP_INVALID;
962  (*consdata)->minabsval = SCIP_INVALID;
963  (*consdata)->minactivity = SCIP_INVALID;
964  (*consdata)->maxactivity = SCIP_INVALID;
965  (*consdata)->lastminactivity = SCIP_INVALID;
966  (*consdata)->lastmaxactivity = SCIP_INVALID;
967  (*consdata)->maxactdelta = SCIP_INVALID;
968  (*consdata)->maxactdeltavar = NULL;
969  (*consdata)->minactivityneginf = -1;
970  (*consdata)->minactivityposinf = -1;
971  (*consdata)->maxactivityneginf = -1;
972  (*consdata)->maxactivityposinf = -1;
973  (*consdata)->minactivityneghuge = -1;
974  (*consdata)->minactivityposhuge = -1;
975  (*consdata)->maxactivityneghuge = -1;
976  (*consdata)->maxactivityposhuge = -1;
977  (*consdata)->glbminactivity = SCIP_INVALID;
978  (*consdata)->glbmaxactivity = SCIP_INVALID;
979  (*consdata)->lastglbminactivity = SCIP_INVALID;
980  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
981  (*consdata)->glbminactivityneginf = -1;
982  (*consdata)->glbminactivityposinf = -1;
983  (*consdata)->glbmaxactivityneginf = -1;
984  (*consdata)->glbmaxactivityposinf = -1;
985  (*consdata)->glbminactivityneghuge = -1;
986  (*consdata)->glbminactivityposhuge = -1;
987  (*consdata)->glbmaxactivityneghuge = -1;
988  (*consdata)->glbmaxactivityposhuge = -1;
989  (*consdata)->possignature = 0;
990  (*consdata)->negsignature = 0;
991  (*consdata)->validmaxabsval = FALSE;
992  (*consdata)->validminabsval = FALSE;
993  (*consdata)->validactivities = FALSE;
994  (*consdata)->validminact = FALSE;
995  (*consdata)->validmaxact = FALSE;
996  (*consdata)->validglbminact = FALSE;
997  (*consdata)->validglbmaxact = FALSE;
998  (*consdata)->boundstightened = 0;
999  (*consdata)->presolved = FALSE;
1000  (*consdata)->removedfixings = FALSE;
1001  (*consdata)->validsignature = FALSE;
1002  (*consdata)->changed = TRUE;
1003  (*consdata)->normalized = FALSE;
1004  (*consdata)->upgradetried = FALSE;
1005  (*consdata)->upgraded = FALSE;
1006  (*consdata)->sorted = (nvars <= 1);
1007  (*consdata)->merged = (nvars <= 1);
1008  (*consdata)->cliquesadded = FALSE;
1009  (*consdata)->implsadded = FALSE;
1010  (*consdata)->binvarssorted = FALSE;
1011  (*consdata)->nbinvars = -1;
1012  (*consdata)->varsdeleted = FALSE;
1013  (*consdata)->rangedrowpropagated = 0;
1014  (*consdata)->checkabsolute = FALSE;
1015 
1016  if( SCIPisTransformed(scip) )
1017  {
1018  /* get transformed variables */
1019  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1020  }
1021 
1022  /* capture variables */
1023  for( v = 0; v < (*consdata)->nvars; v++ )
1024  {
1025  assert((*consdata)->vars[v] != NULL);
1026  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1027  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1028  }
1029 
1030  return SCIP_OKAY;
1031 }
1032 
1033 /** frees a linear constraint data */
1034 static
1036  SCIP* scip, /**< SCIP data structure */
1037  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1038  )
1039 {
1040  int v;
1041 
1042  assert(scip != NULL);
1043  assert(consdata != NULL);
1044  assert(*consdata != NULL);
1045  assert((*consdata)->varssize >= 0);
1046 
1047  /* release the row */
1048  if( (*consdata)->row != NULL )
1049  {
1050  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1051  }
1053  /* release variables */
1054  for( v = 0; v < (*consdata)->nvars; v++ )
1055  {
1056  assert((*consdata)->vars[v] != NULL);
1057  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1058  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1059  }
1060 
1061  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1062  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1063  SCIPfreeBlockMemory(scip, consdata);
1064 
1065  return SCIP_OKAY;
1066 }
1067 
1068 /** prints linear constraint in CIP format to file stream */
1069 static
1071  SCIP* scip, /**< SCIP data structure */
1072  SCIP_CONSDATA* consdata, /**< linear constraint data */
1073  FILE* file /**< output file (or NULL for standard output) */
1074  )
1075 {
1076  assert(scip != NULL);
1077  assert(consdata != NULL);
1078 
1079  /* print left hand side for ranged rows */
1080  if( !SCIPisInfinity(scip, -consdata->lhs)
1081  && !SCIPisInfinity(scip, consdata->rhs)
1082  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1083  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1084 
1085  /* print coefficients and variables */
1086  if( consdata->nvars == 0 )
1087  SCIPinfoMessage(scip, file, "0");
1088  else
1089  {
1090  /* post linear sum of the linear constraint */
1091  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1092  }
1093 
1094  /* print right hand side */
1095  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1096  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1097  else if( !SCIPisInfinity(scip, consdata->rhs) )
1098  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1099  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1100  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1101  else
1102  SCIPinfoMessage(scip, file, " [free]");
1103 
1104  return SCIP_OKAY;
1105 }
1106 
1107 /** prints linear constraint and contained solution values of variables to file stream */
1108 static
1110  SCIP* scip, /**< SCIP data structure */
1111  SCIP_CONS* cons, /**< linear constraint */
1112  SCIP_SOL* sol, /**< solution to print */
1113  FILE* file /**< output file (or NULL for standard output) */
1114  )
1115 {
1116  SCIP_CONSDATA* consdata;
1117 
1118  assert(scip != NULL);
1119  assert(cons != NULL);
1120 
1121  consdata = SCIPconsGetData(cons);
1122  assert(consdata != NULL);
1123 
1125 
1126  /* print left hand side for ranged rows */
1127  if( !SCIPisInfinity(scip, -consdata->lhs)
1128  && !SCIPisInfinity(scip, consdata->rhs)
1129  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1130  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1131 
1132  /* print coefficients and variables */
1133  if( consdata->nvars == 0 )
1134  SCIPinfoMessage(scip, file, "0");
1135  else
1136  {
1137  int v;
1138 
1139  /* post linear sum of the linear constraint */
1140  for( v = 0; v < consdata->nvars; ++v )
1141  {
1142  if( consdata->vals != NULL )
1143  {
1144  if( consdata->vals[v] == 1.0 )
1145  {
1146  if( v > 0 )
1147  SCIPinfoMessage(scip, file, " +");
1148  }
1149  else if( consdata->vals[v] == -1.0 )
1150  SCIPinfoMessage(scip, file, " -");
1151  else
1152  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1153  }
1154  else if( consdata->nvars > 0 )
1155  SCIPinfoMessage(scip, file, " +");
1156 
1157  /* print variable name */
1158  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1159 
1160  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1161  }
1162  }
1163 
1164  /* print right hand side */
1165  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1166  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1167  else if( !SCIPisInfinity(scip, consdata->rhs) )
1168  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1169  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1170  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1171  else
1172  SCIPinfoMessage(scip, file, " [free]");
1173 
1174  SCIPinfoMessage(scip, file, ";\n");
1175 
1176  return SCIP_OKAY;
1177 }
1178 
1179 /** invalidates activity bounds, such that they are recalculated in next get */
1180 static
1182  SCIP_CONSDATA* consdata /**< linear constraint */
1183  )
1184 {
1185  assert(consdata != NULL);
1186 
1187  consdata->validactivities = FALSE;
1188  consdata->validminact = FALSE;
1189  consdata->validmaxact = FALSE;
1190  consdata->validglbminact = FALSE;
1191  consdata->validglbmaxact = FALSE;
1192  consdata->validmaxabsval = FALSE;
1193  consdata->validminabsval = FALSE;
1194  consdata->hasnonbinvalid = FALSE;
1195  consdata->minactivity = SCIP_INVALID;
1196  consdata->maxactivity = SCIP_INVALID;
1197  consdata->lastminactivity = SCIP_INVALID;
1198  consdata->lastmaxactivity = SCIP_INVALID;
1199  consdata->maxabsval = SCIP_INVALID;
1200  consdata->minabsval = SCIP_INVALID;
1201  consdata->maxactdelta = SCIP_INVALID;
1202  consdata->maxactdeltavar = NULL;
1203  consdata->minactivityneginf = -1;
1204  consdata->minactivityposinf = -1;
1205  consdata->maxactivityneginf = -1;
1206  consdata->maxactivityposinf = -1;
1207  consdata->minactivityneghuge = -1;
1208  consdata->minactivityposhuge = -1;
1209  consdata->maxactivityneghuge = -1;
1210  consdata->maxactivityposhuge = -1;
1211  consdata->glbminactivity = SCIP_INVALID;
1212  consdata->glbmaxactivity = SCIP_INVALID;
1213  consdata->lastglbminactivity = SCIP_INVALID;
1214  consdata->lastglbmaxactivity = SCIP_INVALID;
1215  consdata->glbminactivityneginf = -1;
1216  consdata->glbminactivityposinf = -1;
1217  consdata->glbmaxactivityneginf = -1;
1218  consdata->glbmaxactivityposinf = -1;
1219  consdata->glbminactivityneghuge = -1;
1220  consdata->glbminactivityposhuge = -1;
1221  consdata->glbmaxactivityneghuge = -1;
1222  consdata->glbmaxactivityposhuge = -1;
1223 }
1224 
1225 /** compute the pseudo activity of a constraint */
1226 static
1228  SCIP* scip, /**< SCIP data structure */
1229  SCIP_CONSDATA* consdata /**< linear constraint data */
1230  )
1231 {
1232  int i;
1233  int pseudoactivityposinf;
1234  int pseudoactivityneginf;
1235  SCIP_Real pseudoactivity;
1236  SCIP_Real bound;
1237  SCIP_Real val;
1238 
1239  pseudoactivity = 0;
1240  pseudoactivityposinf = 0;
1241  pseudoactivityneginf = 0;
1242 
1243  for( i = consdata->nvars - 1; i >= 0; --i )
1244  {
1245  val = consdata->vals[i];
1246  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1247  if( SCIPisInfinity(scip, bound) )
1248  {
1249  if( val > 0.0 )
1250  pseudoactivityposinf++;
1251  else
1252  pseudoactivityneginf++;
1253  }
1254  else
1255  {
1256  if( SCIPisInfinity(scip, -bound) )
1257  {
1258  if( val > 0.0 )
1259  pseudoactivityneginf++;
1260  else
1261  pseudoactivityposinf++;
1262  }
1263  else
1264  pseudoactivity += val * bound;
1265  }
1266  }
1267 
1268  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1269  return SCIP_INVALID;
1270  else if( pseudoactivityneginf > 0 )
1271  return -SCIPinfinity(scip);
1272  else if( pseudoactivityposinf > 0 )
1273  return SCIPinfinity(scip);
1274 
1275  return pseudoactivity;
1276 }
1277 
1278 /** recompute the minactivity of a constraint */
1279 static
1281  SCIP* scip, /**< SCIP data structure */
1282  SCIP_CONSDATA* consdata /**< linear constraint data */
1283  )
1284 {
1285  int i;
1286  SCIP_Real bound;
1287 
1288  consdata->minactivity = 0;
1289 
1290  for( i = consdata->nvars - 1; i >= 0; --i )
1291  {
1292  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1293  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1294  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1295  consdata->minactivity += consdata->vals[i] * bound;
1296  }
1298  /* the activity was just computed from scratch and is valid now */
1299  consdata->validminact = TRUE;
1300 
1301  /* the activity was just computed from scratch, mark it to be reliable */
1302  consdata->lastminactivity = consdata->minactivity;
1303 }
1304 
1305 /** recompute the maxactivity 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->maxactivity = 0;
1316 
1317  for( i = consdata->nvars - 1; i >= 0; --i )
1318  {
1319  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(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->maxactivity += consdata->vals[i] * bound;
1323  }
1325  /* the activity was just computed from scratch and is valid now */
1326  consdata->validmaxact = TRUE;
1327 
1328  /* the activity was just computed from scratch, mark it to be reliable */
1329  consdata->lastmaxactivity = consdata->maxactivity;
1330 }
1331 
1332 /** recompute the global minactivity 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->glbminactivity = 0;
1343 
1344  for( i = consdata->nvars - 1; i >= 0; --i )
1345  {
1346  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(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->glbminactivity += consdata->vals[i] * bound;
1350  }
1352  /* the activity was just computed from scratch and is valid now */
1353  consdata->validglbminact = TRUE;
1354 
1355  /* the activity was just computed from scratch, mark it to be reliable */
1356  consdata->lastglbminactivity = consdata->glbminactivity;
1357 }
1358 
1359 /** recompute the global maxactivity 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->glbmaxactivity = 0;
1370 
1371  for( i = consdata->nvars - 1; i >= 0; --i )
1372  {
1373  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(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->glbmaxactivity += consdata->vals[i] * bound;
1377  }
1379  /* the activity was just computed from scratch and is valid now */
1380  consdata->validglbmaxact = TRUE;
1381 
1382  /* the activity was just computed from scratch, mark it to be reliable */
1383  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1384 }
1385 
1386 /** calculates maximum absolute value of coefficients */
1387 static
1389  SCIP_CONSDATA* consdata /**< linear constraint data */
1390  )
1391 {
1392  SCIP_Real absval;
1393  int i;
1394 
1395  assert(consdata != NULL);
1396  assert(!consdata->validmaxabsval);
1397  assert(consdata->maxabsval >= SCIP_INVALID);
1398 
1399  consdata->validmaxabsval = TRUE;
1400  consdata->maxabsval = 0.0;
1401  for( i = 0; i < consdata->nvars; ++i )
1402  {
1403  absval = consdata->vals[i];
1404  absval = REALABS(absval);
1405  if( absval > consdata->maxabsval )
1406  consdata->maxabsval = absval;
1407  }
1408 }
1409 
1410 /** calculates minimum absolute value of coefficients */
1411 static
1413  SCIP_CONSDATA* consdata /**< linear constraint data */
1414  )
1415 {
1416  SCIP_Real absval;
1417  int i;
1418 
1419  assert(consdata != NULL);
1420  assert(!consdata->validminabsval);
1421  assert(consdata->minabsval >= SCIP_INVALID);
1422 
1423  consdata->validminabsval = TRUE;
1424 
1425  if( consdata->nvars > 0 )
1426  consdata->minabsval = REALABS(consdata->vals[0]);
1427  else
1428  consdata->minabsval = 0.0;
1430  for( i = 1; i < consdata->nvars; ++i )
1431  {
1432  absval = consdata->vals[i];
1433  absval = REALABS(absval);
1434  if( absval < consdata->minabsval )
1435  consdata->minabsval = absval;
1436  }
1437 }
1438 
1439 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1440 static
1442  SCIP_CONSDATA* consdata /**< linear constraint data */
1443  )
1444 {
1445  int v;
1446 
1447  assert(!consdata->hasnonbinvalid);
1448  consdata->hasnonbinvar = FALSE;
1449  consdata->hascontvar = FALSE;
1450 
1451  for( v = consdata->nvars - 1; v >= 0; --v )
1452  {
1453  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1454 
1455  if( vartype != SCIP_VARTYPE_BINARY )
1456  {
1457  consdata->hasnonbinvar = TRUE;
1459  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1460  {
1461  consdata->hascontvar = TRUE;
1462  break;
1463  }
1464  }
1465  }
1466  assert(consdata->hascontvar || v < 0);
1467 
1468  consdata->hasnonbinvalid = TRUE;
1469 }
1470 
1471 
1472 #ifdef CHECKMAXACTDELTA
1473 /* checks that the stored maximal activity delta (if not invalid) is correct */
1474 static
1476  SCIP* scip, /**< SCIP data structure */
1477  SCIP_CONSDATA* consdata /**< linear constraint data */
1478  )
1479 {
1480  if( consdata->maxactdelta != SCIP_INVALID )
1481  {
1482  SCIP_Real maxactdelta = 0.0;
1483  SCIP_Real domain;
1484  SCIP_Real delta;
1485  SCIP_Real lb;
1486  SCIP_Real ub;
1487  int v;
1488 
1489  for( v = consdata->nvars - 1; v >= 0; --v )
1490  {
1491  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1492  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1493 
1494  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1495  {
1496  maxactdelta = SCIPinfinity(scip);
1497  break;
1498  }
1499 
1500  domain = ub - lb;
1501  delta = REALABS(consdata->vals[v]) * domain;
1502 
1503  if( delta > maxactdelta )
1504  {
1505  maxactdelta = delta;
1506  }
1507  }
1508  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1509  }
1510 }
1511 #else
1512 #define checkMaxActivityDelta(scip, consdata) /**/
1513 #endif
1514 
1515 /** recompute maximal activity contribution for a single variable */
1516 static
1518  SCIP* scip, /**< SCIP data structure */
1519  SCIP_CONSDATA* consdata /**< linear constraint data */
1520  )
1521 {
1522  SCIP_Real delta;
1523  int v;
1524 
1525  consdata->maxactdelta = 0.0;
1526 
1527  if( !consdata->hasnonbinvalid )
1528  consdataCheckNonbinvar(consdata);
1530  /* easy case, the problem consists only of binary variables */
1531  if( !consdata->hasnonbinvar )
1532  {
1533  for( v = consdata->nvars - 1; v >= 0; --v )
1534  {
1535  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1536  {
1537  delta = REALABS(consdata->vals[v]);
1538 
1539  if( delta > consdata->maxactdelta )
1540  {
1541  consdata->maxactdelta = delta;
1542  consdata->maxactdeltavar = consdata->vars[v];
1543  }
1544  }
1545  }
1546  return;
1547  }
1548 
1549  for( v = consdata->nvars - 1; v >= 0; --v )
1550  {
1551  SCIP_Real domain;
1552  SCIP_Real lb;
1553  SCIP_Real ub;
1554 
1555  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1556  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1557 
1558  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1559  {
1560  consdata->maxactdelta = SCIPinfinity(scip);
1561  consdata->maxactdeltavar = consdata->vars[v];
1562  break;
1563  }
1564 
1565  domain = ub - lb;
1566  delta = REALABS(consdata->vals[v]) * domain;
1567 
1568  if( delta > consdata->maxactdelta )
1569  {
1570  consdata->maxactdelta = delta;
1571  consdata->maxactdeltavar = consdata->vars[v];
1572  }
1573  }
1574 }
1575 
1576 
1577 /** updates activities for a change in a bound */
1578 static
1580  SCIP* scip, /**< SCIP data structure */
1581  SCIP_CONSDATA* consdata, /**< linear constraint data */
1582  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1583  SCIP_Real oldbound, /**< old bound of variable */
1584  SCIP_Real newbound, /**< new bound of variable */
1585  SCIP_Real val, /**< coefficient of constraint entry */
1586  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1587  SCIP_Bool global, /**< is it a global or a local bound change? */
1588  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1589  )
1590 {
1591  SCIP_Real* activity;
1592  SCIP_Real* lastactivity;
1593  int* activityposinf;
1594  int* activityneginf;
1595  int* activityposhuge;
1596  int* activityneghuge;
1597  SCIP_Real oldcontribution;
1598  SCIP_Real newcontribution;
1599  SCIP_Real delta;
1600  SCIP_Bool validact;
1601  SCIP_Bool finitenewbound;
1602  SCIP_Bool hugevalnewcont;
1603 
1604  assert(scip != NULL);
1605  assert(consdata != NULL);
1606  assert(global || (var != NULL));
1607  assert(consdata->validactivities);
1608  assert(consdata->minactivity < SCIP_INVALID);
1609  assert(consdata->maxactivity < SCIP_INVALID);
1610  assert(consdata->lastminactivity < SCIP_INVALID);
1611  assert(consdata->lastmaxactivity < SCIP_INVALID);
1612  assert(consdata->minactivityneginf >= 0);
1613  assert(consdata->minactivityposinf >= 0);
1614  assert(consdata->maxactivityneginf >= 0);
1615  assert(consdata->maxactivityposinf >= 0);
1616  assert(consdata->minactivityneghuge >= 0);
1617  assert(consdata->minactivityposhuge >= 0);
1618  assert(consdata->maxactivityneghuge >= 0);
1619  assert(consdata->maxactivityposhuge >= 0);
1620  assert(consdata->glbminactivity < SCIP_INVALID);
1621  assert(consdata->glbmaxactivity < SCIP_INVALID);
1622  assert(consdata->lastglbminactivity < SCIP_INVALID);
1623  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1624  assert(consdata->glbminactivityneginf >= 0);
1625  assert(consdata->glbminactivityposinf >= 0);
1626  assert(consdata->glbmaxactivityneginf >= 0);
1627  assert(consdata->glbmaxactivityposinf >= 0);
1628  assert(consdata->glbminactivityneghuge >= 0);
1629  assert(consdata->glbminactivityposhuge >= 0);
1630  assert(consdata->glbmaxactivityneghuge >= 0);
1631  assert(consdata->glbmaxactivityposhuge >= 0);
1632 
1633  delta = 0.0;
1634 
1635  /* we are updating global activities */
1636  if( global )
1637  {
1638  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1639  * lower bound + pos. coef: update minactivity
1640  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1641  * upper bound + pos. coef: update maxactivity
1642  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1643  */
1644  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1645  {
1646  if( val > 0.0 )
1647  {
1648  activity = &(consdata->glbminactivity);
1649  lastactivity = &(consdata->lastglbminactivity);
1650  activityposinf = &(consdata->glbminactivityposinf);
1651  activityneginf = &(consdata->glbminactivityneginf);
1652  activityposhuge = &(consdata->glbminactivityposhuge);
1653  activityneghuge = &(consdata->glbminactivityneghuge);
1654  validact = consdata->validglbminact;
1655  }
1656  else
1657  {
1658  activity = &(consdata->glbmaxactivity);
1659  lastactivity = &(consdata->lastglbmaxactivity);
1660  activityposinf = &(consdata->glbmaxactivityneginf);
1661  activityneginf = &(consdata->glbmaxactivityposinf);
1662  activityposhuge = &(consdata->glbmaxactivityposhuge);
1663  activityneghuge = &(consdata->glbmaxactivityneghuge);
1664  validact = consdata->validglbmaxact;
1665  }
1666  }
1667  else
1668  {
1669  if( val > 0.0 )
1670  {
1671  activity = &(consdata->glbmaxactivity);
1672  lastactivity = &(consdata->lastglbmaxactivity);
1673  activityposinf = &(consdata->glbmaxactivityposinf);
1674  activityneginf = &(consdata->glbmaxactivityneginf);
1675  activityposhuge = &(consdata->glbmaxactivityposhuge);
1676  activityneghuge = &(consdata->glbmaxactivityneghuge);
1677  validact = consdata->validglbmaxact;
1678  }
1679  else
1680  {
1681  activity = &(consdata->glbminactivity);
1682  lastactivity = &(consdata->lastglbminactivity);
1683  activityposinf = &(consdata->glbminactivityneginf);
1684  activityneginf = &(consdata->glbminactivityposinf);
1685  activityposhuge = &(consdata->glbminactivityposhuge);
1686  activityneghuge = &(consdata->glbminactivityneghuge);
1687  validact = consdata->validglbminact;
1688  }
1689  }
1690  }
1691  /* we are updating local activities */
1692  else
1693  {
1694  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1695  * lower bound + pos. coef: update minactivity
1696  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1697  * upper bound + pos. coef: update maxactivity
1698  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1699  */
1700  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1701  {
1702  if( val > 0.0 )
1703  {
1704  activity = &(consdata->minactivity);
1705  lastactivity = &(consdata->lastminactivity);
1706  activityposinf = &(consdata->minactivityposinf);
1707  activityneginf = &(consdata->minactivityneginf);
1708  activityposhuge = &(consdata->minactivityposhuge);
1709  activityneghuge = &(consdata->minactivityneghuge);
1710  validact = consdata->validminact;
1711  }
1712  else
1713  {
1714  activity = &(consdata->maxactivity);
1715  lastactivity = &(consdata->lastmaxactivity);
1716  activityposinf = &(consdata->maxactivityneginf);
1717  activityneginf = &(consdata->maxactivityposinf);
1718  activityposhuge = &(consdata->maxactivityposhuge);
1719  activityneghuge = &(consdata->maxactivityneghuge);
1720  validact = consdata->validmaxact;
1721  }
1722  }
1723  else
1724  {
1725  if( val > 0.0 )
1726  {
1727  activity = &(consdata->maxactivity);
1728  lastactivity = &(consdata->lastmaxactivity);
1729  activityposinf = &(consdata->maxactivityposinf);
1730  activityneginf = &(consdata->maxactivityneginf);
1731  activityposhuge = &(consdata->maxactivityposhuge);
1732  activityneghuge = &(consdata->maxactivityneghuge);
1733  validact = consdata->validmaxact;
1734  }
1735  else
1736  {
1737  activity = &(consdata->minactivity);
1738  lastactivity = &(consdata->lastminactivity);
1739  activityposinf = &(consdata->minactivityneginf);
1740  activityneginf = &(consdata->minactivityposinf);
1741  activityposhuge = &(consdata->minactivityposhuge);
1742  activityneghuge = &(consdata->minactivityneghuge);
1743  validact = consdata->validminact;
1744  }
1745  }
1746  }
1747 
1748  oldcontribution = val * oldbound;
1749  newcontribution = val * newbound;
1750  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1751  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1752 
1753  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1754  {
1755  /* old bound was +infinity */
1756  if( oldbound > 0.0 )
1757  {
1758  assert((*activityposinf) >= 1);
1759 
1760  /* we only have to do something if the new bound is not again +infinity */
1761  if( finitenewbound || newbound < 0.0 )
1762  {
1763  /* decrease the counter for positive infinite contributions */
1764  (*activityposinf)--;
1765 
1766  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1767  if( !finitenewbound && newbound < 0.0 )
1768  (*activityneginf)++;
1769  else if( hugevalnewcont )
1770  {
1771  /* if the contribution of this variable is too large, increase the counter for huge values */
1772  if( newcontribution > 0.0 )
1773  (*activityposhuge)++;
1774  else
1775  (*activityneghuge)++;
1776  }
1777  /* "normal case": just add the contribution to the activity */
1778  else
1779  delta = newcontribution;
1780  }
1781  }
1782  /* old bound was -infinity */
1783  else
1784  {
1785  assert(oldbound < 0.0);
1786  assert((*activityneginf) >= 1);
1787 
1788  /* we only have to do something ig the new bound is not again -infinity */
1789  if( finitenewbound || newbound > 0.0 )
1790  {
1791  /* decrease the counter for negative infinite contributions */
1792  (*activityneginf)--;
1793 
1794  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1795  if( !finitenewbound && newbound > 0.0 )
1796  (*activityposinf)++;
1797  else if( hugevalnewcont )
1798  {
1799  /* if the contribution of this variable is too large, increase the counter for huge values */
1800  if( newcontribution > 0.0 )
1801  (*activityposhuge)++;
1802  else
1803  (*activityneghuge)++;
1804  }
1805  /* "normal case": just add the contribution to the activity */
1806  else
1807  delta = newcontribution;
1808  }
1809  }
1810  }
1811  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1812  {
1813  /* old contribution was too large and positive */
1814  if( oldcontribution > 0.0 )
1815  {
1816  assert((*activityposhuge) >= 1);
1817 
1818  /* decrease the counter for huge positive contributions; it might be increased again later,
1819  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1820  */
1821  (*activityposhuge)--;
1822 
1823  if( !finitenewbound )
1824  {
1825  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1826  if( newbound > 0.0 )
1827  (*activityposinf)++;
1828  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1829  else
1830  (*activityneginf)++;
1831  }
1832  else if( hugevalnewcont )
1833  {
1834  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1835  if( newcontribution > 0.0 )
1836  (*activityposhuge)++;
1837  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1838  else
1839  (*activityneghuge)++;
1840  }
1841  /* "normal case": just add the contribution to the activity */
1842  else
1843  delta = newcontribution;
1844  }
1845  /* old contribution was too large and negative */
1846  else
1847  {
1848  assert(oldcontribution < 0.0);
1849  assert((*activityneghuge) >= 1);
1850 
1851  /* decrease the counter for huge negative contributions; it might be increased again later,
1852  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1853  */
1854  (*activityneghuge)--;
1855 
1856  if( !finitenewbound )
1857  {
1858  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1859  if( newbound > 0.0 )
1860  (*activityposinf)++;
1861  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1862  else
1863  (*activityneginf)++;
1864  }
1865  else if( hugevalnewcont )
1866  {
1867  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1868  if( newcontribution > 0.0 )
1869  (*activityposhuge)++;
1870  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1871  else
1872  (*activityneghuge)++;
1873  }
1874  /* "normal case": just add the contribution to the activity */
1875  else
1876  delta = newcontribution;
1877  }
1878  }
1879  /* old bound was finite and not too large */
1880  else
1881  {
1882  if( !finitenewbound )
1883  {
1884  /* if the new bound is +infinity, the old contribution has to be subtracted
1885  * and the counter for positive infinite contributions has to be increased
1886  */
1887  if( newbound > 0.0 )
1888  {
1889  (*activityposinf)++;
1890  delta = -oldcontribution;
1891  }
1892  /* if the new bound is -infinity, the old contribution has to be subtracted
1893  * and the counter for negative infinite contributions has to be increased
1894  */
1895  else
1896  {
1897  assert(newbound < 0.0 );
1898 
1899  (*activityneginf)++;
1900  delta = -oldcontribution;
1901  }
1902  }
1903  /* if the contribution of this variable is too large, increase the counter for huge values */
1904  else if( hugevalnewcont )
1905  {
1906  if( newcontribution > 0.0 )
1907  {
1908  (*activityposhuge)++;
1909  delta = -oldcontribution;
1910  }
1911  else
1912  {
1913  (*activityneghuge)++;
1914  delta = -oldcontribution;
1915  }
1916  }
1917  /* "normal case": just update the activity */
1918  else
1919  delta = newcontribution - oldcontribution;
1920  }
1921 
1922  /* update the activity, if the current value is valid and there was a change in the finite part */
1923  if( validact && (delta != 0.0) )
1924  {
1925  /* if the absolute value of the activity is increased, this is regarded as reliable,
1926  * otherwise, we check whether we can still trust the updated value
1927  */
1928  (*activity) = (*activity) + delta;
1929  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1930 
1931  if( REALABS((*lastactivity)) < REALABS(*activity) )
1932  {
1933  (*lastactivity) = (*activity);
1934  }
1935  else
1936  {
1937  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1938  {
1939  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1940  (global ? "global " : ""), (*activity));
1941 
1942  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1943  if( global )
1944  {
1945  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1946  consdata->validglbminact = FALSE;
1947  else
1948  consdata->validglbmaxact = FALSE;
1949  }
1950  else
1951  {
1952  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1953  consdata->validminact = FALSE;
1954  else
1955  consdata->validmaxact = FALSE;
1956  }
1957  }
1958  }
1959  }
1960 }
1961 
1962 /** updates minimum and maximum activity for a change in lower bound */
1963 static
1965  SCIP* scip, /**< SCIP data structure */
1966  SCIP_CONSDATA* consdata, /**< linear constraint data */
1967  SCIP_VAR* var, /**< variable that has been changed */
1968  SCIP_Real oldlb, /**< old lower bound of variable */
1969  SCIP_Real newlb, /**< new lower bound of variable */
1970  SCIP_Real val, /**< coefficient of constraint entry */
1971  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1972  )
1973 {
1974  assert(scip != NULL);
1975  assert(consdata != NULL);
1976  assert(var != NULL);
1977 
1978  if( consdata->validactivities )
1979  {
1980  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1982  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1983  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1984  }
1985 }
1986 
1987 /** updates minimum and maximum activity for a change in upper bound */
1988 static
1990  SCIP* scip, /**< SCIP data structure */
1991  SCIP_CONSDATA* consdata, /**< linear constraint data */
1992  SCIP_VAR* var, /**< variable that has been changed */
1993  SCIP_Real oldub, /**< old upper bound of variable */
1994  SCIP_Real newub, /**< new upper bound of variable */
1995  SCIP_Real val, /**< coefficient of constraint entry */
1996  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1997  )
1998 {
1999  assert(scip != NULL);
2000  assert(consdata != NULL);
2001  assert(var != NULL);
2002 
2003  if( consdata->validactivities )
2004  {
2005  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2007  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
2008  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
2009  }
2010 }
2011 
2012 /** updates minimum and maximum global activity for a change in the global lower bound */
2013 static
2015  SCIP* scip, /**< SCIP data structure */
2016  SCIP_CONSDATA* consdata, /**< linear constraint data */
2017  SCIP_Real oldlb, /**< old lower bound of variable */
2018  SCIP_Real newlb, /**< new lower bound of variable */
2019  SCIP_Real val, /**< coefficient of constraint entry */
2020  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2021  )
2022 {
2023  assert(scip != NULL);
2024  assert(consdata != NULL);
2025 
2026  if( consdata->validactivities )
2027  {
2028  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2029 
2030  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2031  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2032  }
2033 }
2034 
2035 /** updates minimum and maximum global activity for a change in global upper bound */
2036 static
2038  SCIP* scip, /**< SCIP data structure */
2039  SCIP_CONSDATA* consdata, /**< linear constraint data */
2040  SCIP_Real oldub, /**< old upper bound of variable */
2041  SCIP_Real newub, /**< new upper bound of variable */
2042  SCIP_Real val, /**< coefficient of constraint entry */
2043  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2044  )
2045 {
2046  assert(scip != NULL);
2047  assert(consdata != NULL);
2048 
2049  if( consdata->validactivities )
2050  {
2051  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2052 
2053  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2054  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2055  }
2056 }
2057 
2058 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2059 static
2061  SCIP* scip, /**< SCIP data structure */
2062  SCIP_CONSDATA* consdata, /**< linear constraint data */
2063  SCIP_VAR* var, /**< variable of constraint entry */
2064  SCIP_Real val, /**< coefficient of constraint entry */
2065  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2066  )
2067 {
2068  assert(scip != NULL);
2069  assert(consdata != NULL);
2070  assert(var != NULL);
2071 
2072  /* update maximum absolute value */
2073  if( consdata->validmaxabsval )
2074  {
2075  SCIP_Real absval;
2076 
2077  assert(consdata->maxabsval < SCIP_INVALID);
2078 
2079  absval = REALABS(val);
2080  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2081  }
2082 
2083  if( consdata->validminabsval )
2084  {
2085  SCIP_Real absval;
2086 
2087  assert(consdata->minabsval < SCIP_INVALID);
2088 
2089  absval = REALABS(val);
2090  consdata->minabsval = MIN(consdata->minabsval, absval);
2091  }
2092 
2093  /* update minimal and maximal activity */
2094  if( consdata->validactivities )
2095  {
2096  assert(consdata->minactivity < SCIP_INVALID);
2097  assert(consdata->maxactivity < SCIP_INVALID);
2098  assert(consdata->glbminactivity < SCIP_INVALID);
2099  assert(consdata->glbmaxactivity < SCIP_INVALID);
2100 
2101  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2102  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2103  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2104  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2105  }
2106 }
2107 
2108 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2109 static
2111  SCIP* scip, /**< SCIP data structure */
2112  SCIP_CONSDATA* consdata, /**< linear constraint data */
2113  SCIP_VAR* var, /**< variable of constraint entry */
2114  SCIP_Real val, /**< coefficient of constraint entry */
2115  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2116  )
2117 {
2118  assert(scip != NULL);
2119  assert(consdata != NULL);
2120  assert(var != NULL);
2121 
2122  /* invalidate maximum absolute value, if this coefficient was the maximum */
2123  if( consdata->validmaxabsval )
2124  {
2125  SCIP_Real absval;
2126 
2127  absval = REALABS(val);
2128 
2129  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2130  {
2131  consdata->validmaxabsval = FALSE;
2132  consdata->maxabsval = SCIP_INVALID;
2133  }
2134  }
2135 
2136  /* invalidate minimum absolute value, if this coefficient was the minimum */
2137  if( consdata->validminabsval )
2138  {
2139  SCIP_Real absval;
2140 
2141  absval = REALABS(val);
2142 
2143  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2144  {
2145  consdata->validminabsval = FALSE;
2146  consdata->minabsval = SCIP_INVALID;
2147  }
2148  }
2149 
2150  /* update minimal and maximal activity */
2151  if( consdata->validactivities )
2152  {
2153  assert(consdata->minactivity < SCIP_INVALID);
2154  assert(consdata->maxactivity < SCIP_INVALID);
2155  assert(consdata->glbminactivity < SCIP_INVALID);
2156  assert(consdata->glbmaxactivity < SCIP_INVALID);
2157 
2158  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2159  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2160  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2161  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2162  }
2163 }
2164 
2165 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2166 static
2168  SCIP* scip, /**< SCIP data structure */
2169  SCIP_CONSDATA* consdata, /**< linear constraint data */
2170  SCIP_VAR* var, /**< variable of constraint entry */
2171  SCIP_Real oldval, /**< old coefficient of constraint entry */
2172  SCIP_Real newval, /**< new coefficient of constraint entry */
2173  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2174  )
2175 {
2176  assert(scip != NULL);
2177  assert(consdata != NULL);
2178  assert(var != NULL);
2179 
2180  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2181  assert(!SCIPisZero(scip, oldval));
2182 
2183  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2184  assert(!SCIPisZero(scip, newval));
2185 
2186  /* update maximum absolute value */
2187  if( consdata->validmaxabsval )
2188  {
2189  SCIP_Real absval;
2190 
2191  absval = REALABS(newval);
2192 
2193  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2194  {
2195  consdata->maxabsval = absval;
2196  }
2197  else
2198  {
2199  absval = REALABS(oldval);
2200 
2201  /* invalidate maximum absolute value */
2202  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2203  {
2204  consdata->validmaxabsval = FALSE;
2205  consdata->maxabsval = SCIP_INVALID;
2206  }
2207  }
2208  }
2209 
2210  /* update minimum absolute value */
2211  if( consdata->validminabsval )
2212  {
2213  SCIP_Real absval;
2214 
2215  absval = REALABS(newval);
2216 
2217  if( SCIPisLE(scip, absval, consdata->minabsval) )
2218  {
2219  consdata->minabsval = absval;
2220  }
2221  else
2222  {
2223  absval = REALABS(oldval);
2224 
2225  /* invalidate minimum absolute value */
2226  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2227  {
2228  consdata->validminabsval = FALSE;
2229  consdata->minabsval = SCIP_INVALID;
2230  }
2231  }
2232  }
2233 
2234  /* update maximum activity delta */
2235  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2236  {
2237  SCIP_Real domain;
2238  SCIP_Real delta;
2239 
2240  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2241  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2242 
2243  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2244  delta = REALABS(newval) * domain;
2245 
2246  if( delta > consdata->maxactdelta )
2247  {
2248  consdata->maxactdelta = delta;
2249  consdata->maxactdeltavar = var;
2250  }
2251  else
2252  {
2253  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2254  if( consdata->maxactdeltavar == var )
2255  consdata->maxactdelta = SCIP_INVALID;
2256  }
2257  }
2258 
2259  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2260  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2261  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2262 }
2263 
2264 /** returns the maximum absolute value of all coefficients in the constraint */
2265 static
2267  SCIP_CONSDATA* consdata /**< linear constraint data */
2268  )
2269 {
2270  assert(consdata != NULL);
2271 
2272  if( !consdata->validmaxabsval )
2273  consdataCalcMaxAbsval(consdata);
2274  assert(consdata->validmaxabsval);
2275  assert(consdata->maxabsval < SCIP_INVALID);
2276 
2277  return consdata->maxabsval;
2278 }
2279 
2280 /** returns the minimum absolute value of all coefficients in the constraint */
2281 static
2283  SCIP_CONSDATA* consdata /**< linear constraint data */
2284  )
2285 {
2286  assert(consdata != NULL);
2287 
2288  if( !consdata->validminabsval )
2289  consdataCalcMinAbsval(consdata);
2290  assert(consdata->validminabsval);
2291  assert(consdata->minabsval < SCIP_INVALID);
2292 
2293  return consdata->minabsval;
2294 }
2295 
2296 /** calculates minimum and maximum local and global activity for constraint from scratch;
2297  * additionally recalculates maximum absolute value of coefficients
2298  */
2299 static
2301  SCIP* scip, /**< SCIP data structure */
2302  SCIP_CONSDATA* consdata /**< linear constraint data */
2303  )
2304 {
2305  int i;
2306 
2307  assert(scip != NULL);
2308  assert(consdata != NULL);
2309  assert(!consdata->validactivities);
2310  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2311  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2312  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2313  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2314 
2315  consdata->validmaxabsval = TRUE;
2316  consdata->validminabsval = TRUE;
2317  consdata->validactivities = TRUE;
2318  consdata->validminact = TRUE;
2319  consdata->validmaxact = TRUE;
2320  consdata->validglbminact = TRUE;
2321  consdata->validglbmaxact = TRUE;
2322  consdata->maxabsval = 0.0;
2323  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2324  consdata->minactivity = 0.0;
2325  consdata->maxactivity = 0.0;
2326  consdata->lastminactivity = 0.0;
2327  consdata->lastmaxactivity = 0.0;
2328  consdata->minactivityneginf = 0;
2329  consdata->minactivityposinf = 0;
2330  consdata->maxactivityneginf = 0;
2331  consdata->maxactivityposinf = 0;
2332  consdata->minactivityneghuge = 0;
2333  consdata->minactivityposhuge = 0;
2334  consdata->maxactivityneghuge = 0;
2335  consdata->maxactivityposhuge = 0;
2336  consdata->glbminactivity = 0.0;
2337  consdata->glbmaxactivity = 0.0;
2338  consdata->lastglbminactivity = 0.0;
2339  consdata->lastglbmaxactivity = 0.0;
2340  consdata->glbminactivityneginf = 0;
2341  consdata->glbminactivityposinf = 0;
2342  consdata->glbmaxactivityneginf = 0;
2343  consdata->glbmaxactivityposinf = 0;
2344  consdata->glbminactivityneghuge = 0;
2345  consdata->glbminactivityposhuge = 0;
2346  consdata->glbmaxactivityneghuge = 0;
2347  consdata->glbmaxactivityposhuge = 0;
2348 
2349  for( i = 0; i < consdata->nvars; ++i )
2350  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2351 
2352  consdata->lastminactivity = consdata->minactivity;
2353  consdata->lastmaxactivity = consdata->maxactivity;
2354  consdata->lastglbminactivity = consdata->glbminactivity;
2355  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2356 }
2357 
2358 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2359  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2360  */
2361 static
2362 void getMinActivity(
2363  SCIP* scip, /**< SCIP data structure */
2364  SCIP_CONSDATA* consdata, /**< linear constraint */
2365  int posinf, /**< number of coefficients contributing pos. infinite value */
2366  int neginf, /**< number of coefficients contributing neg. infinite value */
2367  int poshuge, /**< number of coefficients contributing huge pos. value */
2368  int neghuge, /**< number of coefficients contributing huge neg. value */
2369  SCIP_Real delta, /**< value to subtract from stored minactivity
2370  * (contribution of the variable set to zero when getting residual activity) */
2371  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2372  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2373  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2374  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2375  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2376  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2377  )
2378 {
2379  assert(scip != NULL);
2380  assert(consdata != NULL);
2381  assert(posinf >= 0);
2382  assert(neginf >= 0);
2383  assert(poshuge >= 0);
2384  assert(neghuge >= 0);
2385  assert(minactivity != NULL);
2386  assert(isrelax != NULL);
2387  assert(issettoinfinity != NULL);
2388 
2389  /* if we have pos. infinite contributions, the minactivity is +infty */
2390  if( posinf > 0 )
2391  {
2392  *minactivity = SCIPinfinity(scip);
2393  *issettoinfinity = TRUE;
2394  *isrelax = FALSE;
2395  }
2396  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2397  else if( neginf > 0 )
2398  {
2399  *minactivity = -SCIPinfinity(scip);
2400  *issettoinfinity = TRUE;
2401  *isrelax = FALSE;
2402  }
2403  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2404  else if( neghuge > 0 )
2405  {
2406  *minactivity = -SCIPinfinity(scip);
2407  *issettoinfinity = TRUE;
2408  *isrelax = TRUE;
2409  }
2410  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2411  else if( !goodrelax && poshuge > 0 )
2412  {
2413  *minactivity = -SCIPinfinity(scip);
2414  *issettoinfinity = TRUE;
2415  *isrelax = TRUE;
2416  }
2417  else
2418  {
2419  SCIP_Real tmpactivity;
2420 
2421  /* recompute minactivity if it is not valid */
2422  if( global )
2423  {
2424  if( !consdata->validglbminact )
2425  consdataRecomputeGlbMinactivity(scip, consdata);
2426  assert(consdata->validglbminact);
2427 
2428  tmpactivity = consdata->glbminactivity;
2429  }
2430  else
2431  {
2432  if( !consdata->validminact )
2433  consdataRecomputeMinactivity(scip, consdata);
2434  assert(consdata->validminact);
2435 
2436  tmpactivity = consdata->minactivity;
2437  }
2438 
2439  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2440  * a feasible relaxation of the minactivity is the number of positive huge contributions
2441  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2442  */
2443  if( poshuge > 0 )
2444  {
2445  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2446  *issettoinfinity = FALSE;
2447  *isrelax = TRUE;
2448  }
2449  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2450  else
2451  {
2452  *minactivity = tmpactivity - delta;
2453  *issettoinfinity = FALSE;
2454  *isrelax = FALSE;
2455  }
2456  }
2457 }
2458 
2459 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2460  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2461  */
2462 static
2463 void getMaxActivity(
2464  SCIP* scip, /**< SCIP data structure */
2465  SCIP_CONSDATA* consdata, /**< linear constraint */
2466  int posinf, /**< number of coefficients contributing pos. infinite value */
2467  int neginf, /**< number of coefficients contributing neg. infinite value */
2468  int poshuge, /**< number of coefficients contributing huge pos. value */
2469  int neghuge, /**< number of coefficients contributing huge neg. value */
2470  SCIP_Real delta, /**< value to subtract from stored maxactivity
2471  * (contribution of the variable set to zero when getting residual activity) */
2472  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2473  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2474  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2475  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2476  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2477  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2478  )
2479 {
2480  assert(scip != NULL);
2481  assert(consdata != NULL);
2482  assert(posinf >= 0);
2483  assert(neginf >= 0);
2484  assert(poshuge >= 0);
2485  assert(neghuge >= 0);
2486  assert(maxactivity != NULL);
2487  assert(isrelax != NULL);
2488  assert(issettoinfinity != NULL);
2489 
2490  /* if we have neg. infinite contributions, the maxactivity is -infty */
2491  if( neginf > 0 )
2492  {
2493  *maxactivity = -SCIPinfinity(scip);
2494  *issettoinfinity = TRUE;
2495  *isrelax = FALSE;
2496  }
2497  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2498  else if( posinf > 0 )
2499  {
2500  *maxactivity = SCIPinfinity(scip);
2501  *issettoinfinity = TRUE;
2502  *isrelax = FALSE;
2503  }
2504  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2505  else if( poshuge > 0 )
2506  {
2507  *maxactivity = SCIPinfinity(scip);
2508  *issettoinfinity = TRUE;
2509  *isrelax = TRUE;
2510  }
2511  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2512  else if( !goodrelax && neghuge > 0 )
2513  {
2514  *maxactivity = SCIPinfinity(scip);
2515  *issettoinfinity = TRUE;
2516  *isrelax = TRUE;
2517  }
2518  else
2519  {
2520  SCIP_Real tmpactivity;
2521 
2522  /* recompute maxactivity if it is not valid */
2523  if( global )
2524  {
2525  if( !consdata->validglbmaxact )
2526  consdataRecomputeGlbMaxactivity(scip, consdata);
2527  assert(consdata->validglbmaxact);
2528 
2529  tmpactivity = consdata->glbmaxactivity;
2530  }
2531  else
2532  {
2533  if( !consdata->validmaxact )
2534  consdataRecomputeMaxactivity(scip, consdata);
2535  assert(consdata->validmaxact);
2536 
2537  tmpactivity = consdata->maxactivity;
2538  }
2539 
2540  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2541  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2542  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2543  */
2544  if( neghuge > 0 )
2545  {
2546  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2547  *issettoinfinity = FALSE;
2548  *isrelax = TRUE;
2549  }
2550  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2551  else
2552  {
2553  *maxactivity = tmpactivity - delta;
2554  *issettoinfinity = FALSE;
2555  *isrelax = FALSE;
2556  }
2557  }
2558 }
2559 
2560 /** gets activity bounds for constraint */
2561 static
2563  SCIP* scip, /**< SCIP data structure */
2564  SCIP_CONSDATA* consdata, /**< linear constraint */
2565  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2566  * relaxed acticities ignored, anyway? */
2567  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2568  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2569  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2570  * i.e. <= the exact minactivity (in case of huge contributions),
2571  * or equal to the exact minimal activity */
2572  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2573  * i.e. >= the exact maxactivity (in case of huge contributions),
2574  * or equal to the exact maximal activity */
2575  )
2576 {
2577  SCIP_Bool issettoinfinity;
2578 
2579  assert(scip != NULL);
2580  assert(consdata != NULL);
2581  assert(minactivity != NULL);
2582  assert(maxactivity != NULL);
2583 
2584  if( !consdata->validactivities )
2585  {
2586  consdataCalcActivities(scip, consdata);
2587  assert(consdata->validminact);
2588  assert(consdata->validmaxact);
2589  }
2590  assert(consdata->minactivity < SCIP_INVALID);
2591  assert(consdata->maxactivity < SCIP_INVALID);
2592  assert(consdata->minactivityneginf >= 0);
2593  assert(consdata->minactivityposinf >= 0);
2594  assert(consdata->maxactivityneginf >= 0);
2595  assert(consdata->maxactivityposinf >= 0);
2596 
2597  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2598  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2599  minactivity, minisrelax, &issettoinfinity);
2600 
2601  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2602  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2603  maxactivity, maxisrelax, &issettoinfinity);
2604 }
2605 
2606 /** calculates activity bounds for constraint after setting variable to zero */
2607 static
2609  SCIP* scip, /**< SCIP data structure */
2610  SCIP_CONSDATA* consdata, /**< linear constraint */
2611  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2612  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2613  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2614  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2615  )
2616 {
2617  SCIP_VAR* var;
2618  SCIP_Real val;
2619  SCIP_Real lb;
2620  SCIP_Real ub;
2621  int v;
2622 
2623  assert(scip != NULL);
2624  assert(consdata != NULL);
2625  assert(cancelvar != NULL);
2626  assert(resactivity != NULL);
2627 
2628  *resactivity = 0.0;
2629 
2630  for( v = 0; v < consdata->nvars; ++v )
2631  {
2632  var = consdata->vars[v];
2633  assert(var != NULL);
2634  if( var == cancelvar )
2635  continue;
2636 
2637  val = consdata->vals[v];
2638 
2639  if( useglobalbounds )
2640  {
2641  lb = SCIPvarGetLbGlobal(var);
2642  ub = SCIPvarGetUbGlobal(var);
2643  }
2644  else
2645  {
2646  lb = SCIPvarGetLbLocal(var);
2647  ub = SCIPvarGetUbLocal(var);
2648  }
2649 
2650  assert(!SCIPisZero(scip, val));
2651  assert(SCIPisLE(scip, lb, ub));
2652 
2653  if( val > 0.0 )
2654  {
2655  if( isminresact )
2656  {
2657  assert(!SCIPisInfinity(scip, -lb));
2658  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2659  *resactivity += val*lb;
2660  }
2661  else
2662  {
2663  assert(!SCIPisInfinity(scip, ub));
2664  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2665  *resactivity += val*ub;
2666  }
2667  }
2668  else
2669  {
2670  if( isminresact)
2671  {
2672  assert(!SCIPisInfinity(scip, ub));
2673  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2674  *resactivity += val*ub;
2675  }
2676  else
2677  {
2678  assert(!SCIPisInfinity(scip, -lb));
2679  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2680  *resactivity += val*lb;
2681  }
2682  }
2683  }
2684  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2685 }
2686 
2687 /** gets activity bounds for constraint after setting variable to zero */
2688 static
2690  SCIP* scip, /**< SCIP data structure */
2691  SCIP_CONSDATA* consdata, /**< linear constraint */
2692  SCIP_VAR* var, /**< variable to calculate activity residual for */
2693  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2694  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2695  * relaxed acticities ignored, anyway? */
2696  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2697  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2698  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2699  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2700  * contributions), or equal to the exact residual minactivity */
2701  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2702  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2703  * contributions), or equal to the exact residual minactivity */
2704  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2705  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2706  )
2707 {
2708  SCIP_Real minactbound;
2709  SCIP_Real maxactbound;
2710  SCIP_Real absval;
2711 
2712  assert(scip != NULL);
2713  assert(consdata != NULL);
2714  assert(var != NULL);
2715  assert(minresactivity != NULL);
2716  assert(maxresactivity != NULL);
2717  assert(minisrelax != NULL);
2718  assert(maxisrelax != NULL);
2719  assert(isminsettoinfinity != NULL);
2720  assert(ismaxsettoinfinity != NULL);
2721 
2722  /* get activity bounds of linear constraint */
2723  if( !consdata->validactivities )
2724  {
2725  consdataCalcActivities(scip, consdata);
2726  assert(consdata->validminact);
2727  assert(consdata->validmaxact);
2728  }
2729  assert(consdata->minactivity < SCIP_INVALID);
2730  assert(consdata->maxactivity < SCIP_INVALID);
2731  assert(consdata->minactivityneginf >= 0);
2732  assert(consdata->minactivityposinf >= 0);
2733  assert(consdata->maxactivityneginf >= 0);
2734  assert(consdata->maxactivityposinf >= 0);
2735  assert(consdata->minactivityneghuge >= 0);
2736  assert(consdata->minactivityposhuge >= 0);
2737  assert(consdata->maxactivityneghuge >= 0);
2738  assert(consdata->maxactivityposhuge >= 0);
2739 
2740  if( val > 0.0 )
2741  {
2742  minactbound = SCIPvarGetLbLocal(var);
2743  maxactbound = SCIPvarGetUbLocal(var);
2744  absval = val;
2745  }
2746  else
2747  {
2748  minactbound = -SCIPvarGetUbLocal(var);
2749  maxactbound = -SCIPvarGetLbLocal(var);
2750  absval = -val;
2751  }
2752 
2753  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2754  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2755  */
2756  if( SCIPisInfinity(scip, minactbound) )
2757  {
2758  assert(consdata->minactivityposinf >= 1);
2759 
2760  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2761  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2762  minresactivity, minisrelax, isminsettoinfinity);
2763  }
2764  else if( SCIPisInfinity(scip, -minactbound) )
2765  {
2766  assert(consdata->minactivityneginf >= 1);
2767 
2768  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2769  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2770  minresactivity, minisrelax, isminsettoinfinity);
2771  }
2772  else if( SCIPisHugeValue(scip, minactbound * absval) )
2773  {
2774  assert(consdata->minactivityposhuge >= 1);
2775 
2776  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2777  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2778  minresactivity, minisrelax, isminsettoinfinity);
2779  }
2780  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2781  {
2782  assert(consdata->minactivityneghuge >= 1);
2783 
2784  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2785  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2786  minresactivity, minisrelax, isminsettoinfinity);
2787  }
2788  else
2789  {
2790  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2791  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2792  minresactivity, minisrelax, isminsettoinfinity);
2793  }
2794 
2795  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2796  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2797  */
2798  if( SCIPisInfinity(scip, -maxactbound) )
2799  {
2800  assert(consdata->maxactivityneginf >= 1);
2801 
2802  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2803  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2804  maxresactivity, maxisrelax, ismaxsettoinfinity);
2805  }
2806  else if( SCIPisInfinity(scip, maxactbound) )
2807  {
2808  assert(consdata->maxactivityposinf >= 1);
2809 
2810  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2811  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2812  maxresactivity, maxisrelax, ismaxsettoinfinity);
2813  }
2814  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2815  {
2816  assert(consdata->maxactivityposhuge >= 1);
2817 
2818  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2819  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2820  maxresactivity, maxisrelax, ismaxsettoinfinity);
2821  }
2822  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2823  {
2824  assert(consdata->maxactivityneghuge >= 1);
2825 
2826  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2827  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2828  maxresactivity, maxisrelax, ismaxsettoinfinity);
2829  }
2830  else
2831  {
2832  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2833  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2834  maxresactivity, maxisrelax, ismaxsettoinfinity);
2835  }
2836 }
2837 
2838 /** gets global activity bounds for constraint */
2839 static
2841  SCIP* scip, /**< SCIP data structure */
2842  SCIP_CONSDATA* consdata, /**< linear constraint */
2843  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2844  * relaxed acticities ignored, anyway? */
2845  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2846  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2847  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2848  * i.e. <= the exact minactivity (in case of huge contributions),
2849  * or equal to the exact minimal activity */
2850  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2851  * i.e. >= the exact maxactivity (in case of huge contributions),
2852  * or equal to the exact maximal activity */
2853  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2854  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2855  )
2856 {
2857  assert(scip != NULL);
2858  assert(consdata != NULL);
2859  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2860  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2861 
2862  if( !consdata->validactivities )
2863  {
2864  consdataCalcActivities(scip, consdata);
2865  assert(consdata->validglbminact);
2866  assert(consdata->validglbmaxact);
2867  }
2868  assert(consdata->glbminactivity < SCIP_INVALID);
2869  assert(consdata->glbmaxactivity < SCIP_INVALID);
2870  assert(consdata->glbminactivityneginf >= 0);
2871  assert(consdata->glbminactivityposinf >= 0);
2872  assert(consdata->glbmaxactivityneginf >= 0);
2873  assert(consdata->glbmaxactivityposinf >= 0);
2874  assert(consdata->glbminactivityneghuge >= 0);
2875  assert(consdata->glbminactivityposhuge >= 0);
2876  assert(consdata->glbmaxactivityneghuge >= 0);
2877  assert(consdata->glbmaxactivityposhuge >= 0);
2878 
2879  if( glbminactivity != NULL )
2880  {
2881  assert(isminsettoinfinity != NULL);
2882  assert(minisrelax != NULL);
2883 
2884  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2885  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2886  glbminactivity, minisrelax, isminsettoinfinity);
2887  }
2888 
2889  if( glbmaxactivity != NULL )
2890  {
2891  assert(ismaxsettoinfinity != NULL);
2892  assert(maxisrelax != NULL);
2893 
2894  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2895  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2896  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2897  }
2898 }
2899 
2900 /** gets global activity bounds for constraint after setting variable to zero */
2901 static
2903  SCIP* scip, /**< SCIP data structure */
2904  SCIP_CONSDATA* consdata, /**< linear constraint */
2905  SCIP_VAR* var, /**< variable to calculate activity residual for */
2906  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2907  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2908  * relaxed acticities ignored, anyway? */
2909  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2910  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2911  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2912  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2913  * contributions), or equal to the exact residual minactivity */
2914  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2915  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2916  * contributions), or equal to the exact residual minactivity */
2917  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2918  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2919  )
2920 {
2921  SCIP_Real minactbound;
2922  SCIP_Real maxactbound;
2923  SCIP_Real absval;
2924 
2925  assert(scip != NULL);
2926  assert(consdata != NULL);
2927  assert(var != NULL);
2928  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2929  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2930 
2931  /* get activity bounds of linear constraint */
2932  if( !consdata->validactivities )
2933  consdataCalcActivities(scip, consdata);
2934 
2935  assert(consdata->glbminactivity < SCIP_INVALID);
2936  assert(consdata->glbmaxactivity < SCIP_INVALID);
2937  assert(consdata->glbminactivityneginf >= 0);
2938  assert(consdata->glbminactivityposinf >= 0);
2939  assert(consdata->glbmaxactivityneginf >= 0);
2940  assert(consdata->glbmaxactivityposinf >= 0);
2941 
2942  if( val > 0.0 )
2943  {
2944  minactbound = SCIPvarGetLbGlobal(var);
2945  maxactbound = SCIPvarGetUbGlobal(var);
2946  absval = val;
2947  }
2948  else
2949  {
2950  minactbound = -SCIPvarGetUbGlobal(var);
2951  maxactbound = -SCIPvarGetLbGlobal(var);
2952  absval = -val;
2953  }
2954 
2955  if( minresactivity != NULL )
2956  {
2957  assert(isminsettoinfinity != NULL);
2958  assert(minisrelax != NULL);
2959 
2960  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2961  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2962  */
2963  if( SCIPisInfinity(scip, minactbound) )
2964  {
2965  assert(consdata->glbminactivityposinf >= 1);
2966 
2967  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2968  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2969  minresactivity, minisrelax, isminsettoinfinity);
2970  }
2971  else if( SCIPisInfinity(scip, -minactbound) )
2972  {
2973  assert(consdata->glbminactivityneginf >= 1);
2974 
2975  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2976  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2977  minresactivity, minisrelax, isminsettoinfinity);
2978  }
2979  else if( SCIPisHugeValue(scip, minactbound * absval) )
2980  {
2981  assert(consdata->glbminactivityposhuge >= 1);
2982 
2983  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2984  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2985  minresactivity, minisrelax, isminsettoinfinity);
2986  }
2987  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2988  {
2989  assert(consdata->glbminactivityneghuge >= 1);
2990 
2991  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2992  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2993  minresactivity, minisrelax, isminsettoinfinity);
2994  }
2995  else
2996  {
2997  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2998  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2999  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3000  }
3001  }
3002 
3003  if( maxresactivity != NULL )
3004  {
3005  assert(ismaxsettoinfinity != NULL);
3006  assert(maxisrelax != NULL);
3007 
3008  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3009  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3010  */
3011  if( SCIPisInfinity(scip, -maxactbound) )
3012  {
3013  assert(consdata->glbmaxactivityneginf >= 1);
3014 
3015  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3016  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3017  maxresactivity, maxisrelax, ismaxsettoinfinity);
3018  }
3019  else if( SCIPisInfinity(scip, maxactbound) )
3020  {
3021  assert(consdata->glbmaxactivityposinf >= 1);
3022 
3023  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3024  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3025  maxresactivity, maxisrelax, ismaxsettoinfinity);
3026  }
3027  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3028  {
3029  assert(consdata->glbmaxactivityposhuge >= 1);
3030 
3031  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3032  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3033  maxresactivity, maxisrelax, ismaxsettoinfinity);
3034  }
3035  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3036  {
3037  assert(consdata->glbmaxactivityneghuge >= 1);
3038 
3039  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3040  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3041  maxresactivity, maxisrelax, ismaxsettoinfinity);
3042  }
3043  else
3044  {
3045  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3046  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3047  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3048  }
3049  }
3050 }
3051 
3052 /** calculates the activity of the linear constraint for given solution */
3053 static
3055  SCIP* scip, /**< SCIP data structure */
3056  SCIP_CONSDATA* consdata, /**< linear constraint data */
3057  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3058  )
3059 {
3060  SCIP_Real activity;
3061 
3062  assert(scip != NULL);
3063  assert(consdata != NULL);
3064 
3065  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3066  activity = consdataComputePseudoActivity(scip, consdata);
3067  else
3068  {
3069  SCIP_Real solval;
3070  int nposinf;
3071  int nneginf;
3072  SCIP_Bool negsign;
3073  int v;
3074 
3075  activity = 0.0;
3076  nposinf = 0;
3077  nneginf = 0;
3078 
3079  for( v = 0; v < consdata->nvars; ++v )
3080  {
3081  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3082 
3083  if( consdata->vals[v] < 0 )
3084  negsign = TRUE;
3085  else
3086  negsign = FALSE;
3087 
3088  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3089  ++nposinf;
3090  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3091  ++nneginf;
3092  else
3093  activity += consdata->vals[v] * solval;
3094  }
3095  assert(nneginf >= 0 && nposinf >= 0);
3096 
3097  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3098 
3099  /* check for amount of infinity values and correct the activity */
3100  if( nposinf > 0 && nneginf > 0 )
3101  activity = (consdata->rhs + consdata->lhs) / 2;
3102  else if( nposinf > 0 )
3103  activity = SCIPinfinity(scip);
3104  else if( nneginf > 0 )
3105  activity = -SCIPinfinity(scip);
3106 
3107  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3108  }
3109 
3110  if( activity == SCIP_INVALID ) /*lint !e777*/
3111  return activity;
3112  else if( activity < 0 )
3113  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3114  else
3115  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3116 
3117  return activity;
3118 }
3119 
3120 /** calculates the feasibility of the linear constraint for given solution */
3121 static
3123  SCIP* scip, /**< SCIP data structure */
3124  SCIP_CONSDATA* consdata, /**< linear constraint data */
3125  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3126  )
3127 {
3128  SCIP_Real activity;
3129 
3130  assert(scip != NULL);
3131  assert(consdata != NULL);
3132 
3133  activity = consdataGetActivity(scip, consdata, sol);
3134 
3135  if( activity == SCIP_INVALID ) /*lint !e777*/
3136  return -SCIPinfinity(scip);
3137 
3138  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3140 
3141 /** updates bit signatures after adding a single coefficient */
3142 static
3144  SCIP_CONSDATA* consdata, /**< linear constraint data */
3145  int pos /**< position of coefficient to update signatures for */
3146  )
3147 {
3148  uint64_t varsignature;
3149  SCIP_Real lb;
3150  SCIP_Real ub;
3151  SCIP_Real val;
3152 
3153  assert(consdata != NULL);
3154  assert(consdata->validsignature);
3155 
3156  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3157  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3158  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3159  val = consdata->vals[pos];
3160  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3161  consdata->possignature |= varsignature;
3162  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3163  consdata->negsignature |= varsignature;
3164 }
3165 
3166 /** calculates the bit signatures of the given constraint data */
3167 static
3169  SCIP_CONSDATA* consdata /**< linear constraint data */
3170  )
3171 {
3172  assert(consdata != NULL);
3173 
3174  if( !consdata->validsignature )
3175  {
3176  int i;
3177 
3178  consdata->validsignature = TRUE;
3179  consdata->possignature = 0;
3180  consdata->negsignature = 0;
3181  for( i = 0; i < consdata->nvars; ++i )
3182  consdataUpdateSignatures(consdata, i);
3183  }
3184 }
3186 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3187 static
3188 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3189 { /*lint --e{715}*/
3190  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3191 
3192  assert(consdata != NULL);
3193  assert(0 <= ind1 && ind1 < consdata->nvars);
3194  assert(0 <= ind2 && ind2 < consdata->nvars);
3195 
3196  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3197 }
3198 
3199 /** permutes the constraint's variables according to a given permutation. */
3200 static
3201 void permSortConsdata(
3202  SCIP_CONSDATA* consdata, /**< the constraint data */
3203  int* perm, /**< the target permutation */
3204  int nvars /**< the number of variables */
3205  )
3206 { /*lint --e{715}*/
3207  SCIP_VAR* varv;
3208  SCIP_EVENTDATA* eventdatav;
3209  SCIP_Real valv;
3210  int v;
3211  int i;
3212  int nexti;
3213 
3214  assert(perm != NULL);
3215  assert(consdata != NULL);
3216 
3217  /* permute the variables in the linear constraint according to the target permutation */
3218  eventdatav = NULL;
3219  for( v = 0; v < nvars; ++v )
3220  {
3221  if( perm[v] != v )
3222  {
3223  varv = consdata->vars[v];
3224  valv = consdata->vals[v];
3225  if( consdata->eventdata != NULL )
3226  eventdatav = consdata->eventdata[v];
3227  i = v;
3228  do
3229  {
3230  assert(0 <= perm[i] && perm[i] < nvars);
3231  assert(perm[i] != i);
3232  consdata->vars[i] = consdata->vars[perm[i]];
3233  consdata->vals[i] = consdata->vals[perm[i]];
3234  if( consdata->eventdata != NULL )
3235  {
3236  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3237  consdata->eventdata[i]->varpos = i;
3238  }
3239  nexti = perm[i];
3240  perm[i] = i;
3241  i = nexti;
3242  }
3243  while( perm[i] != v );
3244  consdata->vars[i] = varv;
3245  consdata->vals[i] = valv;
3246  if( consdata->eventdata != NULL )
3247  {
3248  consdata->eventdata[i] = eventdatav;
3249  consdata->eventdata[i]->varpos = i;
3250  }
3251  perm[i] = i;
3252  }
3253  }
3254 #ifdef SCIP_DEBUG
3255  /* check sorting */
3256  for( v = 0; v < nvars; ++v )
3257  {
3258  assert(perm[v] == v);
3259  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3260  }
3261 #endif
3262 }
3263 
3264 /** sorts linear constraint's variables depending on the stage of the solving process:
3265  * - during PRESOLVING
3266  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3267  * and the variables of the same type by non-decreasing variable index
3268  *
3269  * - during SOLVING
3270  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3271  * This fastens the propagation time of the constraint handler.
3272  */
3273 static
3275  SCIP* scip, /**< SCIP data structure */
3276  SCIP_CONSDATA* consdata /**< linear constraint data */
3277  )
3278 {
3279  assert(scip != NULL);
3280  assert(consdata != NULL);
3281 
3282  /* check if there are variables for sorting */
3283  if( consdata->nvars <= 1 )
3284  {
3285  consdata->sorted = TRUE;
3286  consdata->binvarssorted = TRUE;
3287  }
3288  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3289  {
3290  int* perm;
3292  /* get temporary memory to store the sorted permutation */
3293  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3294 
3295  /* call sorting method */
3296  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3297 
3298  permSortConsdata(consdata, perm, consdata->nvars);
3299 
3300  /* free temporary memory */
3301  SCIPfreeBufferArray(scip, &perm);
3302 
3303  consdata->sorted = TRUE;
3304  consdata->binvarssorted = FALSE;
3305  }
3306  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3307  {
3308  SCIP_EVENTDATA** eventdata;
3309  SCIP_VAR** vars;
3310  SCIP_Real* vals;
3311  int nvars;
3312  int v;
3313  int lastbin;
3314 
3315  nvars = consdata->nvars;
3316  vars = consdata->vars;
3317  vals = consdata->vals;
3318  eventdata = consdata->eventdata;
3319  assert(vars != NULL || nvars == 0);
3320  assert(vals != NULL || nvars == 0);
3321 
3322  lastbin = 0;
3323  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3324  for( v = 0; v < nvars; ++v )
3325  {
3326  assert( vars != NULL); /* for flexelint */
3327  assert( vals != NULL); /* for flexelint */
3328  if( SCIPvarIsBinary(vars[v]) )
3329  {
3330  /* swap variable at the end of the binary variables, if necessary */
3331  if( lastbin < v )
3332  {
3333  SCIP_VAR* tmpvar;
3334  SCIP_Real tmpval;
3335 
3336  tmpvar = vars[lastbin];
3337  tmpval = vals[lastbin];
3338 
3339  vars[lastbin] = vars[v];
3340  vals[lastbin] = vals[v];
3341 
3342  vars[v] = tmpvar;
3343  vals[v] = tmpval;
3344 
3345  if( eventdata != NULL )
3346  {
3347  SCIP_EVENTDATA* tmpeventdata;
3348 
3349  tmpeventdata = eventdata[lastbin];
3350  eventdata[lastbin] = eventdata[v];
3351  eventdata[lastbin]->varpos = lastbin;
3352  eventdata[v] = tmpeventdata;
3353  eventdata[v]->varpos = v;
3354  }
3355  assert(SCIPvarIsBinary(vars[lastbin]));
3356  }
3357 #ifndef NDEBUG
3358  else
3359  assert(lastbin == v);
3360 #endif
3361  ++lastbin;
3362  }
3363  }
3364  consdata->nbinvars = lastbin;
3365 
3366 #ifndef NDEBUG
3367  /* check sorting */
3368  for( v = 0; v < nvars; ++v )
3369  {
3370  assert(vars != NULL); /* for flexelint */
3371  assert(eventdata == NULL || eventdata[v]->varpos == v);
3372  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3373  }
3374 #endif
3375 
3376  if( consdata->nbinvars > 1 )
3377  {
3378  SCIP_Real* absvals;
3379  int* perm;
3380 
3381  assert(lastbin == consdata->nbinvars);
3382  assert(lastbin <= nvars);
3383  assert(vals != NULL);
3384 
3385  /* initialize absolute coefficients and the target permutation for binary variables */
3386  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3387  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3388 
3389  for( v = 0; v < lastbin; ++v )
3390  {
3391  absvals[v] = ABS(vals[v]);
3392  perm[v] = v;
3393  }
3394 
3395  /* execute the sorting */
3396  SCIPsortDownRealInt(absvals, perm, lastbin);
3397 
3398  permSortConsdata(consdata, perm, lastbin);
3399 
3400  /* free temporary arrays */
3401  SCIPfreeBufferArray(scip, &perm);
3402  SCIPfreeBufferArray(scip, &absvals);
3403  }
3404  consdata->binvarssorted = TRUE;
3405 
3406  /* presolve sorting cannot be guaranteed after binary sorting */
3407  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3408  }
3409  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3410  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3411 
3412  return SCIP_OKAY;
3413 }
3414 
3415 
3416 /*
3417  * local linear constraint handler methods
3418  */
3419 
3420 /** sets left hand side of linear constraint */
3421 static
3423  SCIP* scip, /**< SCIP data structure */
3424  SCIP_CONS* cons, /**< linear constraint */
3425  SCIP_Real lhs /**< new left hand side */
3426  )
3427 {
3428  SCIP_CONSDATA* consdata;
3429  SCIP_Bool locked;
3430  int i;
3431 
3432  assert(scip != NULL);
3433  assert(cons != NULL);
3434  assert(!SCIPisInfinity(scip, lhs));
3435 
3436  /* adjust value to not be smaller than -inf */
3437  if ( SCIPisInfinity(scip, -lhs) )
3438  lhs = -SCIPinfinity(scip);
3440  consdata = SCIPconsGetData(cons);
3441  assert(consdata != NULL);
3442  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3443  assert(!SCIPisInfinity(scip, consdata->lhs));
3444 
3445  /* check whether the side is not changed */
3446  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3447  return SCIP_OKAY;
3448 
3449  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3450  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3451  {
3452  consdata->rhs = lhs;
3453  assert(consdata->row == NULL);
3454  }
3455 
3456  locked = FALSE;
3457  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3458  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3459 
3460  /* if necessary, update the rounding locks of variables */
3461  if( locked )
3462  {
3463  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3464  {
3465  SCIP_VAR** vars;
3466  SCIP_Real* vals;
3467  int v;
3468 
3469  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3470  vars = consdata->vars;
3471  vals = consdata->vals;
3472 
3473  for( v = 0; v < consdata->nvars; ++v )
3474  {
3475  assert(vars[v] != NULL);
3476  assert(!SCIPisZero(scip, vals[v]));
3477 
3478  if( SCIPisPositive(scip, vals[v]) )
3479  {
3480  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3481  }
3482  else
3483  {
3484  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3485  }
3486  }
3487  }
3488  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3489  {
3490  SCIP_VAR** vars;
3491  SCIP_Real* vals;
3492  int v;
3493 
3494  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3495  vars = consdata->vars;
3496  vals = consdata->vals;
3497 
3498  for( v = 0; v < consdata->nvars; ++v )
3499  {
3500  assert(vars[v] != NULL);
3501  assert(!SCIPisZero(scip, vals[v]));
3502 
3503  if( SCIPisPositive(scip, vals[v]) )
3504  {
3505  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3506  }
3507  else
3508  {
3509  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3510  }
3511  }
3512  }
3513  }
3514 
3515  /* 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 */
3516  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3517  {
3518  consdata->boundstightened = 0;
3519  consdata->presolved = FALSE;
3520  consdata->cliquesadded = FALSE;
3521  consdata->implsadded = FALSE;
3522 
3523  /* mark the constraint for propagation */
3524  if( SCIPconsIsTransformed(cons) )
3525  {
3526  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3527  }
3528  }
3529 
3530  /* set new left hand side and update constraint data */
3531  consdata->lhs = lhs;
3532  consdata->changed = TRUE;
3533  consdata->normalized = FALSE;
3534  consdata->upgradetried = FALSE;
3535  consdata->rangedrowpropagated = 0;
3536 
3537  /* update the lhs of the LP row */
3538  if( consdata->row != NULL )
3539  {
3540  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3541  }
3542 
3543  return SCIP_OKAY;
3544 }
3545 
3546 /** sets right hand side of linear constraint */
3547 static
3549  SCIP* scip, /**< SCIP data structure */
3550  SCIP_CONS* cons, /**< linear constraint */
3551  SCIP_Real rhs /**< new right hand side */
3552  )
3553 {
3554  SCIP_CONSDATA* consdata;
3555  SCIP_Bool locked;
3556  int i;
3557 
3558  assert(scip != NULL);
3559  assert(cons != NULL);
3560  assert(!SCIPisInfinity(scip, -rhs));
3561 
3562  /* adjust value to not be larger than inf */
3563  if ( SCIPisInfinity(scip, rhs) )
3564  rhs = SCIPinfinity(scip);
3566  consdata = SCIPconsGetData(cons);
3567  assert(consdata != NULL);
3568  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3569  assert(!SCIPisInfinity(scip, -consdata->rhs));
3570 
3571  /* check whether the side is not changed */
3572  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3573  return SCIP_OKAY;
3574 
3575  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3576  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3577  {
3578  consdata->lhs = rhs;
3579  assert(consdata->row == NULL);
3580  }
3581 
3582  locked = FALSE;
3583  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3584  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3585 
3586  /* if necessary, update the rounding locks of variables */
3587  if( locked )
3588  {
3589  assert(SCIPconsIsTransformed(cons));
3590 
3591  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3592  {
3593  SCIP_VAR** vars;
3594  SCIP_Real* vals;
3595  int v;
3596 
3597  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3598  vars = consdata->vars;
3599  vals = consdata->vals;
3600 
3601  for( v = 0; v < consdata->nvars; ++v )
3602  {
3603  assert(vars[v] != NULL);
3604  assert(!SCIPisZero(scip, vals[v]));
3605 
3606  if( SCIPisPositive(scip, vals[v]) )
3607  {
3608  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3609  }
3610  else
3611  {
3612  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3613  }
3614  }
3615  }
3616  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3617  {
3618  SCIP_VAR** vars;
3619  SCIP_Real* vals;
3620  int v;
3621 
3622  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3623  vars = consdata->vars;
3624  vals = consdata->vals;
3625 
3626  for( v = 0; v < consdata->nvars; ++v )
3627  {
3628  assert(vars[v] != NULL);
3629  assert(!SCIPisZero(scip, vals[v]));
3630 
3631  if( SCIPisPositive(scip, vals[v]) )
3632  {
3633  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3634  }
3635  else
3636  {
3637  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3638  }
3639  }
3640  }
3641  }
3642 
3643  /* 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 */
3644  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3645  {
3646  consdata->boundstightened = 0;
3647  consdata->presolved = FALSE;
3648  consdata->cliquesadded = FALSE;
3649  consdata->implsadded = FALSE;
3650 
3651  /* mark the constraint for propagation */
3652  if( SCIPconsIsTransformed(cons) )
3653  {
3654  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3655  }
3656  }
3657 
3658  /* set new right hand side and update constraint data */
3659  consdata->rhs = rhs;
3660  consdata->changed = TRUE;
3661  consdata->normalized = FALSE;
3662  consdata->upgradetried = FALSE;
3663  consdata->rangedrowpropagated = 0;
3664 
3665  /* update the rhs of the LP row */
3666  if( consdata->row != NULL )
3667  {
3668  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3669  }
3670 
3671  return SCIP_OKAY;
3672 }
3673 
3674 /** adds coefficient in linear constraint */
3675 static
3677  SCIP* scip, /**< SCIP data structure */
3678  SCIP_CONS* cons, /**< linear constraint */
3679  SCIP_VAR* var, /**< variable of constraint entry */
3680  SCIP_Real val /**< coefficient of constraint entry */
3681  )
3682 {
3683  SCIP_CONSDATA* consdata;
3684  SCIP_Bool transformed;
3685 
3686  assert(scip != NULL);
3687  assert(cons != NULL);
3688  assert(var != NULL);
3689 
3690  /* ignore coefficient if it is nearly zero */
3691  if( SCIPisZero(scip, val) )
3692  return SCIP_OKAY;
3694  consdata = SCIPconsGetData(cons);
3695  assert(consdata != NULL);
3696 
3697  /* are we in the transformed problem? */
3698  transformed = SCIPconsIsTransformed(cons);
3699 
3700  /* always use transformed variables in transformed constraints */
3701  if( transformed )
3702  {
3703  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3704  }
3705  assert(var != NULL);
3706  assert(transformed == SCIPvarIsTransformed(var));
3707 
3708  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3709  consdata->vars[consdata->nvars] = var;
3710  consdata->vals[consdata->nvars] = val;
3711  consdata->nvars++;
3712 
3713  /* capture variable */
3714  SCIP_CALL( SCIPcaptureVar(scip, var) );
3715 
3716  /* if we are in transformed problem, the variable needs an additional event data */
3717  if( transformed )
3718  {
3719  if( consdata->eventdata != NULL )
3720  {
3721  SCIP_CONSHDLR* conshdlr;
3722  SCIP_CONSHDLRDATA* conshdlrdata;
3723 
3724  /* check for event handler */
3725  conshdlr = SCIPconsGetHdlr(cons);
3726  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3727  assert(conshdlrdata != NULL);
3728  assert(conshdlrdata->eventhdlr != NULL);
3729 
3730  /* initialize eventdata array */
3731  consdata->eventdata[consdata->nvars-1] = NULL;
3732 
3733  /* catch bound change events of variable */
3734  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3735  }
3736 
3737  /* update minimum and maximum activities */
3738  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3739 
3740  /* update maximum activity delta */
3741  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3742  {
3743  SCIP_Real lb;
3744  SCIP_Real ub;
3745 
3746  lb = SCIPvarGetLbLocal(var);
3747  ub = SCIPvarGetUbLocal(var);
3748 
3749  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3750  {
3751  consdata->maxactdelta = SCIPinfinity(scip);
3752  consdata->maxactdeltavar = var;
3753  }
3754  else
3755  {
3756  SCIP_Real domain = ub - lb;
3757  SCIP_Real delta = REALABS(val) * domain;
3758 
3759  if( delta > consdata->maxactdelta )
3760  {
3761  consdata->maxactdelta = delta;
3762  consdata->maxactdeltavar = var;
3763  }
3764  }
3765  }
3766  }
3767 
3768  /* install rounding locks for new variable */
3769  SCIP_CALL( lockRounding(scip, cons, var, val) );
3770 
3771  /* mark the constraint for propagation */
3772  if( transformed )
3773  {
3774  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3775  }
3776 
3777  consdata->boundstightened = 0;
3778  consdata->presolved = FALSE;
3779  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3780 
3781  if( consdata->validsignature )
3782  consdataUpdateSignatures(consdata, consdata->nvars-1);
3783 
3784  consdata->changed = TRUE;
3785  consdata->normalized = FALSE;
3786  consdata->upgradetried = FALSE;
3787  consdata->cliquesadded = FALSE;
3788  consdata->implsadded = FALSE;
3789  consdata->rangedrowpropagated = 0;
3790 
3791  if( consdata->nvars == 1 )
3792  {
3793  consdata->binvarssorted = TRUE;
3794  consdata->sorted = TRUE;
3795  consdata->merged = TRUE;
3796  }
3797  else
3798  {
3799  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3800  consdata->sorted = consdata->sorted
3801  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3802  consdata->merged = FALSE;
3803  }
3804 
3805  /* update hascontvar and hasnonbinvar flags */
3806  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3807  {
3808  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3809 
3810  if( vartype != SCIP_VARTYPE_BINARY )
3811  {
3812  consdata->hasnonbinvar = TRUE;
3813 
3814  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3815  consdata->hascontvar = TRUE;
3816  }
3817  }
3818 
3819  /* add the new coefficient to the LP row */
3820  if( consdata->row != NULL )
3821  {
3822  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3823  }
3824 
3825  return SCIP_OKAY;
3826 }
3827 
3828 /** deletes coefficient at given position from linear constraint data */
3829 static
3831  SCIP* scip, /**< SCIP data structure */
3832  SCIP_CONS* cons, /**< linear constraint */
3833  int pos /**< position of coefficient to delete */
3834  )
3835 {
3836  SCIP_CONSDATA* consdata;
3837  SCIP_VAR* var;
3838  SCIP_Real val;
3839 
3840  assert(scip != NULL);
3841  assert(cons != NULL);
3842 
3843  consdata = SCIPconsGetData(cons);
3844  assert(consdata != NULL);
3845  assert(0 <= pos && pos < consdata->nvars);
3846 
3847  var = consdata->vars[pos];
3848  val = consdata->vals[pos];
3849  assert(var != NULL);
3850 
3851  /* remove rounding locks for deleted variable */
3852  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3853 
3854  /* if we are in transformed problem, delete the event data of the variable */
3855  if( SCIPconsIsTransformed(cons) )
3856  {
3857  SCIP_CONSHDLR* conshdlr;
3858  SCIP_CONSHDLRDATA* conshdlrdata;
3859 
3860  /* check for event handler */
3861  conshdlr = SCIPconsGetHdlr(cons);
3862  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3863  assert(conshdlrdata != NULL);
3864  assert(conshdlrdata->eventhdlr != NULL);
3865 
3866  /* drop bound change events of variable */
3867  if( consdata->eventdata != NULL )
3868  {
3869  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3870  assert(consdata->eventdata[pos] == NULL);
3871  }
3872  }
3873 
3874  /* move the last variable to the free slot */
3875  if( pos != consdata->nvars-1 )
3876  {
3877  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3878 
3879  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3880  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3881 
3882  if( consdata->eventdata != NULL )
3883  {
3884  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3885  assert(consdata->eventdata[pos] != NULL);
3886  consdata->eventdata[pos]->varpos = pos;
3887  }
3888  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3889  }
3890  consdata->nvars--;
3891 
3892  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3893  * of the remaining variable, or give exactly 0.0)
3894  */
3895  if( consdata->nvars <= 1 )
3896  consdataInvalidateActivities(consdata);
3897  else
3898  {
3899  if( SCIPconsIsTransformed(cons) )
3900  {
3901  /* if we are in transformed problem, update minimum and maximum activities */
3902  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3903 
3904  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3905  * delta needs to be recalculated on the next real propagation
3906  */
3907  if( consdata->maxactdeltavar == var )
3908  {
3909  consdata->maxactdelta = SCIP_INVALID;
3910  consdata->maxactdeltavar = NULL;
3911  }
3912  }
3913  }
3914 
3915  /* mark the constraint for propagation */
3916  if( SCIPconsIsTransformed(cons) )
3917  {
3918  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3919  }
3920 
3921  consdata->boundstightened = 0;
3922  consdata->presolved = FALSE;
3923  consdata->validsignature = FALSE;
3924  consdata->changed = TRUE;
3925  consdata->normalized = FALSE;
3926  consdata->upgradetried = FALSE;
3927  consdata->cliquesadded = FALSE;
3928  consdata->implsadded = FALSE;
3929  consdata->rangedrowpropagated = 0;
3930 
3931  /* check if hasnonbinvar flag might be incorrect now */
3932  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3933  {
3934  consdata->hasnonbinvalid = FALSE;
3935  }
3936 
3937  /* delete coefficient from the LP row */
3938  if( consdata->row != NULL )
3939  {
3940  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3941  }
3942 
3943  /* release variable */
3944  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3945 
3946  return SCIP_OKAY;
3947 }
3948 
3949 /** changes coefficient value at given position of linear constraint data */
3950 static
3952  SCIP* scip, /**< SCIP data structure */
3953  SCIP_CONS* cons, /**< linear constraint */
3954  int pos, /**< position of coefficient to delete */
3955  SCIP_Real newval /**< new value of coefficient */
3956  )
3957 {
3958  SCIP_CONSDATA* consdata;
3959  SCIP_VAR* var;
3960  SCIP_Real val;
3961  SCIP_Bool locked;
3962  int i;
3963 
3964  assert(scip != NULL);
3965  assert(cons != NULL);
3966  assert(!SCIPisZero(scip, newval));
3967 
3968  consdata = SCIPconsGetData(cons);
3969  assert(consdata != NULL);
3970  assert(0 <= pos && pos < consdata->nvars);
3971  assert(!SCIPisZero(scip, newval));
3972 
3973  var = consdata->vars[pos];
3974  val = consdata->vals[pos];
3975  assert(var != NULL);
3976  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3977 
3978  locked = FALSE;
3979  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3980  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3981 
3982  /* if necessary, update the rounding locks of the variable */
3983  if( locked && newval * val < 0.0 )
3984  {
3985  assert(SCIPconsIsTransformed(cons));
3986 
3987  /* remove rounding locks for variable with old coefficient */
3988  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3989 
3990  /* install rounding locks for variable with new coefficient */
3991  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3992  }
3993 
3994  /* change the value */
3995  consdata->vals[pos] = newval;
3996 
3997  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3998 
3999  /* update minimum and maximum activities */
4000  if( SCIPconsIsTransformed(cons) )
4001  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4002 
4003  /* mark the constraint for propagation */
4004  if( SCIPconsIsTransformed(cons) )
4005  {
4006  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4007  }
4008 
4009  consdata->boundstightened = 0;
4010  consdata->presolved = FALSE;
4011  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4012  consdata->changed = TRUE;
4013  consdata->normalized = FALSE;
4014  consdata->upgradetried = FALSE;
4015  consdata->cliquesadded = FALSE;
4016  consdata->implsadded = FALSE;
4017  consdata->rangedrowpropagated = 0;
4018 
4019  return SCIP_OKAY;
4020 }
4021 
4022 /** scales a linear constraint with a constant scalar */
4023 static
4025  SCIP* scip, /**< SCIP data structure */
4026  SCIP_CONS* cons, /**< linear constraint to scale */
4027  SCIP_Real scalar /**< value to scale constraint with */
4028  )
4029 {
4030  SCIP_CONSDATA* consdata;
4031  SCIP_Real newval;
4032  SCIP_Real absscalar;
4033  int i;
4034 
4035  assert(scip != NULL);
4036  assert(cons != NULL);
4037 
4038  consdata = SCIPconsGetData(cons);
4039  assert(consdata != NULL);
4040  assert(consdata->row == NULL);
4041  assert(!SCIPisEQ(scip, scalar, 1.0));
4042 
4043  /* scale the coefficients */
4044  for( i = consdata->nvars - 1; i >= 0; --i )
4045  {
4046  newval = scalar * consdata->vals[i];
4047 
4048  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4049  * flooring down our new value
4050  */
4051  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4052  newval = SCIPfeasFloor(scip, newval + 0.5);
4053 
4054  if( SCIPisZero(scip, newval) )
4055  {
4056  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4057  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4058  SCIP_CALL( delCoefPos(scip, cons, i) );
4059  }
4060  else
4061  consdata->vals[i] = newval;
4062  }
4063 
4064  /* scale the sides */
4065  if( scalar < 0.0 )
4066  {
4067  SCIP_Real lhs;
4068 
4069  lhs = consdata->lhs;
4070  consdata->lhs = -consdata->rhs;
4071  consdata->rhs = -lhs;
4072  }
4073  absscalar = REALABS(scalar);
4074  if( !SCIPisInfinity(scip, -consdata->lhs) )
4075  {
4076  newval = absscalar * consdata->lhs;
4077 
4078  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4079  * flooring down our new value
4080  */
4081  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4082  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4083  else
4084  consdata->lhs = newval;
4085  }
4086  if( !SCIPisInfinity(scip, consdata->rhs) )
4087  {
4088  newval = absscalar * consdata->rhs;
4089 
4090  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4091  * our new value
4092  */
4093  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4094  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4095  else
4096  consdata->rhs = newval;
4097  }
4098 
4099  consdataInvalidateActivities(consdata);
4100  consdata->cliquesadded = FALSE;
4101  consdata->implsadded = FALSE;
4102 
4103  return SCIP_OKAY;
4104 }
4105 
4106 /* perform deletion of variables in all constraints of the constraint handler */
4107 static
4109  SCIP* scip, /**< SCIP data structure */
4110  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4111  SCIP_CONS** conss, /**< array of constraints */
4112  int nconss /**< number of constraints */
4113  )
4114 {
4115  SCIP_CONSDATA* consdata;
4116  int i;
4117  int v;
4118 
4119  assert(scip != NULL);
4120  assert(conshdlr != NULL);
4121  assert(conss != NULL);
4122  assert(nconss >= 0);
4123  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4124 
4125  /* iterate over all constraints */
4126  for( i = 0; i < nconss; i++ )
4127  {
4128  consdata = SCIPconsGetData(conss[i]);
4129 
4130  /* constraint is marked, that some of its variables were deleted */
4131  if( consdata->varsdeleted )
4132  {
4133  /* iterate over all variables of the constraint and delete them from the constraint */
4134  for( v = consdata->nvars - 1; v >= 0; --v )
4135  {
4136  if( SCIPvarIsDeleted(consdata->vars[v]) )
4137  {
4138  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4139  }
4140  }
4141  consdata->varsdeleted = FALSE;
4142  }
4143  }
4144 
4145  return SCIP_OKAY;
4146 }
4147 
4148 
4149 /** normalizes a linear constraint with the following rules:
4150  * - if all coefficients have them same absolute value, change them to (-)1.0
4151  * - multiplication with +1 or -1:
4152  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4153  * if the current rule doesn't determine the sign):
4154  * 1. the right hand side must not be negative
4155  * 2. the right hand side must not be infinite
4156  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4157  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4158  * 5. multiply with +1
4159  * - rationals to integrals
4160  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4161  * by the smallest common multiple of all denominators to get integral coefficients.
4162  * Forbid large denominators due to numerical stability.
4163  * - division by greatest common divisor
4164  * If all coefficients are integral, divide them by the greatest common divisor.
4165  */
4166 static
4168  SCIP* scip, /**< SCIP data structure */
4169  SCIP_CONS* cons, /**< linear constraint to normalize */
4170  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4171  )
4172 {
4173  SCIP_CONSDATA* consdata;
4174  SCIP_VAR** vars;
4175  SCIP_Real* vals;
4176  SCIP_Longint scm;
4177  SCIP_Longint nominator;
4178  SCIP_Longint denominator;
4179  SCIP_Longint gcd;
4180  SCIP_Longint maxmult;
4181  SCIP_Real epsilon;
4182  SCIP_Real feastol;
4183  SCIP_Real maxabsval;
4184  SCIP_Real minabsval;
4185  SCIP_Bool success;
4186  SCIP_Bool onlyintegral;
4187  int nvars;
4188  int mult;
4189  int nposcoeffs;
4190  int nnegcoeffs;
4191  int i;
4192  int v;
4193 
4194  assert(scip != NULL);
4195  assert(cons != NULL);
4196 
4197  *infeasible = FALSE;
4198 
4199  /* we must not change a modifiable constraint in any way */
4200  if( SCIPconsIsModifiable(cons) )
4201  return SCIP_OKAY;
4202 
4203  /* get constraint data */
4204  consdata = SCIPconsGetData(cons);
4205  assert(consdata != NULL);
4206 
4207  /* check, if the constraint is already normalized */
4208  if( consdata->normalized )
4209  return SCIP_OKAY;
4210 
4211  /* get coefficient arrays */
4212  vals = consdata->vals;
4213  nvars = consdata->nvars;
4214  vars = consdata->vars;
4215  assert(nvars == 0 || vars != NULL);
4216  assert(nvars == 0 || vals != NULL);
4217 
4218  if( nvars == 0 )
4219  {
4220  consdata->normalized = TRUE;
4221  return SCIP_OKAY;
4222  }
4223 
4224  assert(vars != NULL);
4225  assert(vals != NULL);
4226 
4227  /* get maximal and minimal absolute coefficient */
4228  maxabsval = consdataGetMaxAbsval(consdata);
4229  minabsval = consdataGetMinAbsval(consdata);
4230 
4231  /* return if scaling by maxval will eliminate coefficients */
4232  if( SCIPisZero(scip, minabsval/maxabsval) )
4233  return SCIP_OKAY;
4234 
4235  /* check if all coefficients are in absolute value equal, and not 1.0 */
4236  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4237  {
4238  SCIP_Bool abscoefsequ;
4239 
4240  abscoefsequ = TRUE;
4241 
4242  for( v = nvars - 1; v >= 0; --v )
4243  {
4244  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4245  {
4246  abscoefsequ = FALSE;
4247  break;
4248  }
4249  }
4250 
4251  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4252  if( abscoefsequ )
4253  {
4254  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4255  SCIPdebugPrintCons(scip, cons, NULL);
4256  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4257 
4258  if( consdata->validmaxabsval )
4259  {
4260  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4261  consdata->maxabsval = 1.0;
4262  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4263  consdata->minabsval = 1.0;
4264 
4265  maxabsval = 1.0;
4266  }
4267  else
4268  {
4269  /* get maximal absolute coefficient */
4270  maxabsval = consdataGetMaxAbsval(consdata);
4271  }
4272 
4273  /* get new consdata information, because scaleCons() might have deleted variables */
4274  vals = consdata->vals;
4275  nvars = consdata->nvars;
4276  vars = consdata->vars;
4277 
4278  assert(nvars == 0 || vars != NULL);
4279  assert(nvars == 0 || vals != NULL);
4280  }
4281  }
4282 
4283  /* nvars might have changed */
4284  if( nvars == 0 )
4285  {
4286  consdata->normalized = TRUE;
4287  return SCIP_OKAY;
4288  }
4289 
4290  assert(vars != NULL);
4291  assert(vals != NULL);
4292 
4293  /* calculate the maximal multiplier for common divisor calculation:
4294  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4295  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4296  * additionally, we don't want to scale the constraint if this would lead to too
4297  * large coefficients
4298  */
4299  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4300  feastol = SCIPfeastol(scip);
4301  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4302  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
4303 
4304  if( !consdata->hasnonbinvalid )
4305  consdataCheckNonbinvar(consdata);
4306 
4307  /* if all variables are of integral type we will allow a greater multiplier */
4308  if( !consdata->hascontvar )
4309  {
4310  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
4311  {
4312  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0))));
4313  }
4314  }
4315  else
4316  {
4317  SCIP_Bool foundcont;
4318 
4319  foundcont = FALSE;
4320 
4321  for( v = nvars - 1; v >= 0; --v )
4322  {
4323  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4324  {
4325  foundcont = TRUE;
4326  break;
4327  }
4328  }
4329 
4330  if( !foundcont )
4331  {
4332  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0))));
4333  }
4334  }
4335 
4336  /*
4337  * multiplication with +1 or -1
4338  */
4339  mult = 0;
4340 
4341  /* 1. the right hand side must not be negative */
4342  if( SCIPisPositive(scip, consdata->lhs) )
4343  mult = +1;
4344  else if( SCIPisNegative(scip, consdata->rhs) )
4345  mult = -1;
4346 
4347  if( mult == 0 )
4348  {
4349  /* 2. the right hand side must not be infinite */
4350  if( SCIPisInfinity(scip, -consdata->lhs) )
4351  mult = +1;
4352  else if( SCIPisInfinity(scip, consdata->rhs) )
4353  mult = -1;
4354  }
4355 
4356  if( mult == 0 )
4357  {
4358  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4359  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4360  mult = +1;
4361  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4362  mult = -1;
4363  }
4364 
4365  if( mult == 0 )
4366  {
4367  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4368  nposcoeffs = 0;
4369  nnegcoeffs = 0;
4370  for( i = 0; i < nvars; ++i )
4371  {
4372  if( vals[i] > 0.0 )
4373  nposcoeffs++;
4374  else
4375  nnegcoeffs++;
4376  }
4377  if( nposcoeffs > nnegcoeffs )
4378  mult = +1;
4379  else if( nposcoeffs < nnegcoeffs )
4380  mult = -1;
4381  }
4382 
4383  if( mult == 0 )
4384  {
4385  /* 5. multiply with +1 */
4386  mult = +1;
4387  }
4388 
4389  assert(mult == +1 || mult == -1);
4390  if( mult == -1 )
4391  {
4392  /* scale the constraint with -1 */
4393  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4394  SCIPdebugPrintCons(scip, cons, NULL);
4395  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4396 
4397  /* scalecons() can delete variables, but scaling with -1 should not do that */
4398  assert(nvars == consdata->nvars);
4399  }
4400 
4401  /*
4402  * rationals to integrals
4403  *
4404  * @todo try scaling only on behalf of non-continuous variables
4405  */
4406  success = TRUE;
4407  scm = 1;
4408  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4409  {
4410  if( !SCIPisIntegral(scip, vals[i]) )
4411  {
4412  /* epsilon has been slightly decreased above - to be on the safe side */
4413  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4414  if( success )
4415  scm = SCIPcalcSmaComMul(scm, denominator);
4416  }
4417  }
4418  assert(scm >= 1);
4419 
4420  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4421  * their greatest common divisor
4422  */
4423  onlyintegral = TRUE;
4424  if( scm == 1 )
4425  {
4426  for( i = nvars - 1; i >= 0; --i )
4427  {
4428  if( !SCIPisIntegral(scip, vals[i]) )
4429  {
4430  onlyintegral = FALSE;
4431  break;
4432  }
4433  }
4434  }
4435 
4436  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4437  if( success && scm != 1 )
4438  {
4439  /* scale the constraint with the smallest common multiple of all denominators */
4440  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4441  SCIPdebugPrintCons(scip, cons, NULL);
4442  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4443 
4444  if( consdata->validmaxabsval )
4445  {
4446  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4447  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4448  {
4449  consdata->validmaxabsval = FALSE;
4450  consdata->maxabsval = SCIP_INVALID;
4451  consdataCalcMaxAbsval(consdata);
4452  }
4453  }
4454 
4455  if( consdata->validminabsval )
4456  {
4457  consdata->minabsval *= REALABS((SCIP_Real)scm);
4458  if( !SCIPisIntegral(scip, consdata->minabsval) )
4459  {
4460  consdata->validminabsval = FALSE;
4461  consdata->minabsval = SCIP_INVALID;
4462  consdataCalcMinAbsval(consdata);
4463  }
4464  }
4465 
4466  /* get new consdata information, because scalecons() might have deleted variables */
4467  vals = consdata->vals;
4468  nvars = consdata->nvars;
4469  assert(nvars == 0 || vals != NULL);
4470  }
4471 
4472  /*
4473  * division by greatest common divisor
4474  */
4475  if( success && nvars >= 1 )
4476  {
4477  /* all coefficients are integral: divide them by their greatest common divisor */
4478  assert(SCIPisIntegral(scip, vals[0]));
4479 
4480  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4481  for( i = 1; i < nvars && gcd > 1; ++i )
4482  {
4483  assert(SCIPisIntegral(scip, vals[i]));
4484  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4485  }
4486 
4487  if( gcd > 1 )
4488  {
4489  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4490  if( !consdata->hascontvar && onlyintegral )
4491  {
4492  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4493  {
4494  *infeasible = TRUE;
4495 
4496  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%g:\n", gcd);
4497  SCIPdebugPrintCons(scip, cons, NULL);
4498 
4499  return SCIP_OKAY;
4500  }
4501  }
4502 
4503  /* divide the constraint by the greatest common divisor of the coefficients */
4504  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4505  SCIPdebugPrintCons(scip, cons, NULL);
4506  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4507 
4508  if( consdata->validmaxabsval )
4509  {
4510  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4511  }
4512  if( consdata->validminabsval )
4513  {
4514  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4515  }
4516  }
4517  }
4518 
4519  /* mark constraint to be normalized */
4520  consdata->normalized = TRUE;
4521 
4522  SCIPdebugMsg(scip, "normalized constraint:\n");
4523  SCIPdebugPrintCons(scip, cons, NULL);
4524 
4525  return SCIP_OKAY;
4526 }
4527 
4528 /** replaces multiple occurrences of a variable by a single coefficient */
4529 static
4531  SCIP* scip, /**< SCIP data structure */
4532  SCIP_CONS* cons /**< linear constraint */
4533  )
4534 {
4535  SCIP_CONSDATA* consdata;
4536  SCIP_VAR* var;
4537  SCIP_Real valsum;
4538  int v;
4539 
4540  assert(scip != NULL);
4541  assert(cons != NULL);
4542 
4543  consdata = SCIPconsGetData(cons);
4544  assert(consdata != NULL);
4545 
4546  if( consdata->merged )
4547  return SCIP_OKAY;
4548 
4549  /* sort the constraint */
4550  SCIP_CALL( consdataSort(scip, consdata) );
4551 
4552  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4553  * backward direction is necessary, since delCoefPos() modifies the given position and
4554  * the subsequent ones
4555  */
4556  v = consdata->nvars-1;
4557  while( v >= 1 )
4558  {
4559  var = consdata->vars[v];
4560  if( consdata->vars[v-1] == var )
4561  {
4562  valsum = consdata->vals[v];
4563  do
4564  {
4565  SCIP_CALL( delCoefPos(scip, cons, v) );
4566  --v;
4567  valsum += consdata->vals[v];
4568  }
4569  while( v >= 1 && consdata->vars[v-1] == var );
4570 
4571  /* modify the last existing occurrence of the variable */
4572  assert(consdata->vars[v] == var);
4573  if( SCIPisZero(scip, valsum) )
4574  {
4575  SCIP_CALL( delCoefPos(scip, cons, v) );
4576 
4577  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4578  * delta needs to be recalculated on the next real propagation
4579  */
4580  if( consdata->maxactdeltavar == var )
4581  {
4582  consdata->maxactdelta = SCIP_INVALID;
4583  consdata->maxactdeltavar = NULL;
4584  }
4585  }
4586  else
4587  {
4588  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4589  }
4590  }
4591  --v;
4592  }
4593 
4594  consdata->merged = TRUE;
4595 
4596  return SCIP_OKAY;
4597 }
4598 
4599 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4600 static
4602  SCIP* scip, /**< SCIP data structure */
4603  SCIP_CONS* cons, /**< linear constraint */
4604  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4605  * information is not needed; in this case, we apply all fixings
4606  * instead of stopping after the first infeasible one */
4607  )
4608 {
4609  SCIP_CONSDATA* consdata;
4610  SCIP_VAR* var;
4611  SCIP_VAR** aggrvars;
4612  SCIP_Real val;
4613  SCIP_Real* aggrscalars;
4614  SCIP_Real fixedval;
4615  SCIP_Real aggrconst;
4616  int v;
4617  int naggrvars;
4618  int i;
4619 
4620  assert(scip != NULL);
4621  assert(cons != NULL);
4622 
4623  if( infeasible != NULL )
4624  *infeasible = FALSE;
4625 
4626  consdata = SCIPconsGetData(cons);
4627  assert(consdata != NULL);
4628 
4629  if( !consdata->removedfixings )
4630  {
4631  SCIP_Real lhssubtrahend;
4632  SCIP_Real rhssubtrahend;
4633 
4634  lhssubtrahend = 0.0;
4635  rhssubtrahend = 0.0;
4636 
4637  SCIPdebugMsg(scip, "applying fixings:\n");
4638  SCIPdebugPrintCons(scip, cons, NULL);
4639 
4640  v = 0;
4641  while( v < consdata->nvars )
4642  {
4643  var = consdata->vars[v];
4644  val = consdata->vals[v];
4645  assert(SCIPvarIsTransformed(var));
4646 
4647  switch( SCIPvarGetStatus(var) )
4648  {
4650  SCIPerrorMessage("original variable in transformed linear constraint\n");
4651  return SCIP_INVALIDDATA;
4652 
4653  case SCIP_VARSTATUS_LOOSE:
4654  case SCIP_VARSTATUS_COLUMN:
4655  ++v;
4656  break;
4657 
4658  case SCIP_VARSTATUS_FIXED:
4659  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4660  fixedval = SCIPvarGetLbGlobal(var);
4661  if( !SCIPisInfinity(scip, -consdata->lhs) )
4662  {
4663  if( SCIPisInfinity(scip, ABS(fixedval)) )
4664  {
4665  if( val * fixedval > 0.0 )
4666  {
4667  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4668  }
4669  else
4670  {
4671  if( infeasible != NULL )
4672  {
4673  /* if lhs gets infinity it means that the problem is infeasible */
4674  *infeasible = TRUE;
4675  return SCIP_OKAY;
4676  }
4677  else
4678  {
4679  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4680  }
4681  }
4682  }
4683  else
4684  lhssubtrahend += val * fixedval;
4685  }
4686  if( !SCIPisInfinity(scip, consdata->rhs) )
4687  {
4688  if( SCIPisInfinity(scip, ABS(fixedval)) )
4689  {
4690  if( val * fixedval > 0.0 )
4691  {
4692  if( infeasible != NULL )
4693  {
4694  /* if rhs gets -infinity it means that the problem is infeasible */
4695  *infeasible = TRUE;
4696  return SCIP_OKAY;
4697  }
4698  else
4699  {
4700  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4701  }
4702  }
4703  else
4704  {
4705  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4706  }
4707  }
4708  else
4709  rhssubtrahend += val * fixedval;
4710  }
4711  SCIP_CALL( delCoefPos(scip, cons, v) );
4712  break;
4713 
4715  {
4716  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4717  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4718  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4719 
4720  assert(activevar != NULL);
4721  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4722  assert(activevar != NULL);
4723 
4724  if( !SCIPisZero(scip, activescalar) )
4725  {
4726  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4727  }
4728 
4729  if( !SCIPisZero(scip, activeconstant) )
4730  {
4731  if( !SCIPisInfinity(scip, -consdata->lhs) )
4732  lhssubtrahend += activeconstant;
4733  if( !SCIPisInfinity(scip, consdata->rhs) )
4734  rhssubtrahend += activeconstant;
4735  }
4736 
4737  SCIP_CALL( delCoefPos(scip, cons, v) );
4738  break;
4739  }
4742  naggrvars = SCIPvarGetMultaggrNVars(var);
4743  aggrvars = SCIPvarGetMultaggrVars(var);
4744  aggrscalars = SCIPvarGetMultaggrScalars(var);
4745  for( i = 0; i < naggrvars; ++i )
4746  {
4747  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4748  }
4749  aggrconst = SCIPvarGetMultaggrConstant(var);
4750 
4751  if( !SCIPisInfinity(scip, -consdata->lhs) )
4752  lhssubtrahend += val * aggrconst;
4753  if( !SCIPisInfinity(scip, consdata->rhs) )
4754  rhssubtrahend += val * aggrconst;
4755 
4756  SCIP_CALL( delCoefPos(scip, cons, v) );
4757  break;
4758 
4760  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4761  aggrconst = SCIPvarGetNegationConstant(var);
4762 
4763  if( !SCIPisInfinity(scip, -consdata->lhs) )
4764  lhssubtrahend += val * aggrconst;
4765  if( !SCIPisInfinity(scip, consdata->rhs) )
4766  rhssubtrahend += val * aggrconst;
4767 
4768  SCIP_CALL( delCoefPos(scip, cons, v) );
4769  break;
4770 
4771  default:
4772  SCIPerrorMessage("unknown variable status\n");
4773  SCIPABORT();
4774  return SCIP_INVALIDDATA; /*lint !e527*/
4775  }
4776  }
4777 
4778  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4779  {
4780  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4781  * causing wrong fixings of other variables --> better use a real zero here;
4782  * for small numbers, polishing the difference might lead to wrong results -->
4783  * better use the exact difference in this case
4784  */
4785  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4786  {
4787  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4788  }
4789  else
4790  {
4791  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4792  }
4793  }
4794  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4795  {
4796  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4797  * causing wrong fixings of other variables --> better use a real zero here;
4798  * for small numbers, polishing the difference might lead to wrong results -->
4799  * better use the exact difference in this case
4800  */
4801  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4802  {
4803  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4804  }
4805  else
4806  {
4807  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4808  }
4809  }
4810 
4811  consdata->removedfixings = TRUE;
4812 
4813  SCIPdebugMsg(scip, "after fixings:\n");
4814  SCIPdebugPrintCons(scip, cons, NULL);
4815 
4816  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4817  * to clean up the constraint
4818  */
4819  SCIP_CALL( mergeMultiples(scip, cons) );
4820 
4821  SCIPdebugMsg(scip, "after merging:\n");
4822  SCIPdebugPrintCons(scip, cons, NULL);
4823  }
4824  assert(consdata->removedfixings);
4825 
4826 #ifndef NDEBUG
4827  /* check, if all fixings are applied */
4828  for( v = 0; v < consdata->nvars; ++v )
4829  assert(SCIPvarIsActive(consdata->vars[v]));
4830 #endif
4831 
4832  return SCIP_OKAY;
4833 }
4834 
4835 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4836  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4837  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4838  * conflict detecting constraint by using NULL as inferred variable
4839  */
4840 static
4842  SCIP* scip, /**< SCIP data structure */
4843  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4844  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4845  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4846  int inferpos, /**< position of the inferred variable in the vars array */
4847  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4848  )
4849 {
4850  SCIP_CONSDATA* consdata;
4851  SCIP_VAR** vars;
4852  SCIP_Real* vals;
4853  int nvars;
4854  int i;
4855 
4856  assert(scip != NULL);
4857  assert(cons != NULL);
4859  consdata = SCIPconsGetData(cons);
4860 
4861  assert(consdata != NULL);
4862 
4863  vars = consdata->vars;
4864  vals = consdata->vals;
4865  nvars = consdata->nvars;
4866 
4867  assert(vars != NULL || nvars == 0);
4868  assert(vals != NULL || nvars == 0);
4869 
4870  assert(-1 <= inferpos && inferpos < nvars);
4871  assert((infervar == NULL) == (inferpos == -1));
4872  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4873 
4874  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4875  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4876  * - if the right hand side is the reason, the minimal residual activity is responsible
4877  * - if the left hand side is the reason, the maximal residual activity is responsible
4878  */
4879 
4880  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4881  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4882  {
4883  SCIP_Real minresactivity;
4884  SCIP_Real maxresactivity;
4885  SCIP_Bool minisrelax;
4886  SCIP_Bool maxisrelax;
4887  SCIP_Bool isminsettoinfinity;
4888  SCIP_Bool ismaxsettoinfinity;
4889 
4890  minresactivity = -SCIPinfinity(scip);
4891  maxresactivity = SCIPinfinity(scip);
4892 
4893  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4894  if( infervar != NULL )
4895  {
4896  assert(vals != NULL); /* for flexelint */
4897  if( reasonisrhs )
4898  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4899  &minisrelax, NULL, &isminsettoinfinity, NULL);
4900  else
4901  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4902  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4903  }
4904  else
4905  {
4906  if( reasonisrhs )
4907  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4908  &minisrelax, NULL, &isminsettoinfinity, NULL);
4909  else
4910  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4911  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4912  }
4913 
4914  /* we can only do something clever, if the residual activity is finite and not relaxed */
4915  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4916  {
4917  SCIP_Real rescap;
4918  SCIP_Bool resactisinf;
4919 
4920  resactisinf = FALSE;
4921 
4922  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4923  * than its inferred bound
4924  */
4925  if( infervar != NULL )
4926  {
4927  assert(vals != NULL); /* for flexelint */
4928 
4929  if( reasonisrhs )
4930  {
4931  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4932  {
4933  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4934  if( SCIPisInfinity(scip, -minresactivity) )
4935  resactisinf = TRUE;
4936  }
4937  rescap = consdata->rhs - minresactivity;
4938  }
4939  else
4940  {
4941  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4942  {
4943  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4944  if( SCIPisInfinity(scip, maxresactivity) )
4945  resactisinf = TRUE;
4946  }
4947  rescap = consdata->lhs - maxresactivity;
4948  }
4949 
4950  if( reasonisrhs == (vals[inferpos] > 0.0) )
4951  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4952  else
4953  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4954  }
4955  else
4956  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4957 
4958  if( !resactisinf )
4959  {
4960  /* now add bounds as reasons until the residual capacity is exceeded */
4961  for( i = 0; i < nvars; ++i )
4962  {
4963  assert( vars != NULL && vals != NULL ); /* for lint */
4964 
4965  /* zero coefficients and the infered variable can be ignored */
4966  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4967  continue;
4968 
4969  /* check if the residual capacity is exceeded */
4970  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4971  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4972  break;
4973 
4974  /* update the residual capacity due to the local bound of this variable */
4975  if( reasonisrhs == (vals[i] > 0.0) )
4976  {
4977  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4978  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4979  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4980  }
4981  else
4982  {
4983  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4984  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4985  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4986  }
4987  }
4988  return SCIP_OKAY;
4989  }
4990  }
4991  }
4992 
4993  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4994  for( i = 0; i < nvars; ++i )
4995  {
4996  assert(vars != NULL); /* for flexelint */
4997  assert(vals != NULL); /* for flexelint */
4998 
4999  /* zero coefficients and the infered variable can be ignored */
5000  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5001  continue;
5002 
5003  if( reasonisrhs == (vals[i] > 0.0) )
5004  {
5005  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5006  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5007  }
5008  else
5009  {
5010  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5011  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5012  }
5013  }
5014 
5015  return SCIP_OKAY;
5016 }
5017 
5018 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5019  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5020  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5021  */
5022 static
5024  SCIP* scip, /**< SCIP data structure */
5025  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5026  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5027  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5028  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5029  )
5030 {
5031  SCIP_CONSDATA* consdata;
5032  SCIP_VAR** vars;
5033  int nvars;
5034  int v;
5035 
5036  assert(scip != NULL);
5037  assert(cons != NULL);
5038 
5039  consdata = SCIPconsGetData(cons);
5040  assert(consdata != NULL);
5041  vars = consdata->vars;
5042  nvars = consdata->nvars;
5043  assert(vars != NULL || nvars == 0);
5044  assert(-1 <= inferpos && inferpos < nvars);
5045  assert((infervar == NULL) == (inferpos == -1));
5046  assert(inferpos == -1 || vars != NULL);
5047  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5048 
5049  /* collect all fixed variables */
5050  for( v = nvars - 1; v >= 0; --v )
5051  {
5052  assert(vars != NULL); /* for flexelint */
5053 
5054  /* need to add old bounds before propagation of inferrence variable */
5055  if( vars[v] == infervar )
5056  {
5057  assert(vars[v] != NULL);
5058 
5059  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5060  {
5061  /* @todo get boundchange index before this last boundchange and correct the index */
5062  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5063  }
5064 
5065  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5066  {
5067  /* @todo get boundchange index before this last boundchange and correct the index */
5068  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5069  }
5070 
5071  continue;
5072  }
5073 
5074  /* check for fixed variables */
5075  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5076  {
5077  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5078  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5079  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5080  }
5081  }
5082 
5083  return SCIP_OKAY;
5084 }
5085 
5086 /** add reasoning variables to conflict candidate queue which led to the conflict */
5087 static
5089  SCIP* scip, /**< SCIP data structure */
5090  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5091  int nvars, /**< number of variables reasoning the infeasibility */
5092  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5093  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5094  )
5095 {
5096  int v;
5097 
5098  assert(scip != NULL);
5099 
5100  /* collect all variables for which the local bounds differ from their global bounds */
5101  for( v = nvars - 1; v >= 0; --v )
5102  {
5103  assert(vars != NULL);
5104 
5105  /* check for local bound changes variables */
5106  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5107  {
5108  /* add conflict bound */
5109  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5110  }
5111 
5112  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5113  {
5114  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5115  }
5116  }
5117 
5118  if( var != NULL )
5119  {
5120  if( bound < SCIPvarGetLbLocal(var) )
5121  {
5122  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5123  }
5124 
5125  if( bound > SCIPvarGetUbLocal(var) )
5126  {
5127  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5128  }
5129  }
5130 
5131  return SCIP_OKAY;
5132 }
5133 
5134 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5135  * propagation rule (see propagateCons()):
5136  * (1) activity residuals of all other variables tighten bounds of single variable
5137  */
5138 static
5140  SCIP* scip, /**< SCIP data structure */
5141  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5142  SCIP_VAR* infervar, /**< variable that was deduced */
5143  INFERINFO inferinfo, /**< inference information */
5144  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5145  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5146  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5147  )
5148 {
5149  SCIP_CONSDATA* consdata;
5150  SCIP_VAR** vars;
5151 #ifndef NDEBUG
5152  SCIP_Real* vals;
5153 #endif
5154  int nvars;
5155  int inferpos;
5157  assert(scip != NULL);
5158  assert(cons != NULL);
5159  assert(result != NULL);
5160 
5161  consdata = SCIPconsGetData(cons);
5162  assert(consdata != NULL);
5163  vars = consdata->vars;
5164  nvars = consdata->nvars;
5165 #ifndef NDEBUG
5166  vals = consdata->vals;
5167  assert(vars != NULL);
5168  assert(vals != NULL);
5169 #endif
5170 
5171  /* get the position of the inferred variable in the vars array */
5172  inferpos = inferInfoGetPos(inferinfo);
5173  if( inferpos >= nvars || vars[inferpos] != infervar )
5174  {
5175  /* find inference variable in constraint */
5176  /**@todo use a binary search here; the variables can be sorted by variable index */
5177  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5178  {}
5179  }
5180  assert(inferpos < nvars);
5181  assert(vars[inferpos] == infervar);
5182  assert(!SCIPisZero(scip, vals[inferpos]));
5183 
5184  switch( inferInfoGetProprule(inferinfo) )
5185  {
5186  case PROPRULE_1_RHS:
5187  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5188  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5189  * domain in order to not exceed the right hand side of the inequality
5190  */
5191  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5192  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5193  *result = SCIP_SUCCESS;
5194  break;
5195 
5196  case PROPRULE_1_LHS:
5197  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5198  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5199  * domain in order to not fall below the left hand side of the inequality
5200  */
5201  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5202  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5203  *result = SCIP_SUCCESS;
5204  break;
5205 
5206  case PROPRULE_1_RANGEDROW:
5207  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5208  * the given inference variable to their bounds in this given ranged row
5209  */
5210 
5211  /* check that we really have a ranged row here */
5212  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5213  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5214  *result = SCIP_SUCCESS;
5215  break;
5216 
5217  case PROPRULE_INVALID:
5218  default:
5219  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5220  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5221  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5222  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5223  SCIPinfoMessage(scip, NULL, ";\n");
5224  return SCIP_INVALIDDATA;
5225  }
5226 
5227  return SCIP_OKAY;
5228 }
5229 
5230 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5231 static
5233  SCIP* scip, /**< SCIP data structure */
5234  SCIP_CONS* cons, /**< conflict detecting constraint */
5235  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5236  )
5237 {
5238  /* conflict analysis can only be applied in solving stage and if it is turned on */
5240  return SCIP_OKAY;
5241 
5242  /* initialize conflict analysis */
5244 
5245  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5246  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5247 
5248  /* analyze the conflict */
5250 
5251  return SCIP_OKAY;
5252 }
5253 
5254 /** check if there is any hope of tightening some bounds */
5255 static
5257  SCIP* scip, /**< SCIP data structure */
5258  SCIP_CONS* cons /**< linear constraint */
5259  )
5260 {
5261  SCIP_CONSDATA* consdata;
5262  int infcountmin;
5263  int infcountmax;
5264 
5265  consdata = SCIPconsGetData(cons);
5266  assert(consdata != NULL);
5267 
5268  infcountmin = consdata->minactivityneginf
5269  + consdata->minactivityposinf
5270  + consdata->minactivityneghuge
5271  + consdata->minactivityposhuge;
5272  infcountmax = consdata->maxactivityneginf
5273  + consdata->maxactivityposinf
5274  + consdata->maxactivityneghuge
5275  + consdata->maxactivityposhuge;
5276 
5277  if( infcountmin > 1 && infcountmax > 1 )
5278  return FALSE;
5279 
5280  return TRUE;
5281 }
5282 
5283 /** tighten upper bound */
5284 static
5286  SCIP* scip, /**< SCIP data structure */
5287  SCIP_CONS* cons, /**< linear constraint */
5288  int pos, /**< variable position */
5289  PROPRULE proprule, /**< propagation rule that deduced the value */
5290  SCIP_Real newub, /**< new upper bound */
5291  SCIP_Real oldub, /**< old upper bound */
5292  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5293  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5294  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5295  )
5296 {
5297  SCIP_CONSDATA* consdata;
5298  SCIP_VAR* var;
5299  SCIP_Real lb;
5300  SCIP_Bool infeasible;
5301  SCIP_Bool tightened;
5303  assert(cons != NULL);
5304  assert(!SCIPisInfinity(scip, newub));
5305 
5306  consdata = SCIPconsGetData(cons);
5307  assert(consdata != NULL);
5308  var = consdata->vars[pos];
5309  assert(var != NULL);
5310 
5311  lb = SCIPvarGetLbLocal(var);
5312  newub = SCIPadjustedVarUb(scip, var, newub);
5313 
5314  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5315  {
5316  SCIP_VARTYPE vartype;
5317 
5318  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5319  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5320 
5321  vartype = SCIPvarGetType(var);
5322 
5323  /* tighten upper bound */
5324  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5325 
5326  if( infeasible )
5327  {
5328  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5329  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5330 
5331  /* analyze conflict */
5332  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5333 
5334  *cutoff = TRUE;
5335  }
5336  else if( tightened )
5337  {
5338  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5339  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5340  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5341 
5342  (*nchgbds)++;
5343 
5344  /* if variable type was changed we might be able to upgrade the constraint */
5345  if( vartype != SCIPvarGetType(var) )
5346  consdata->upgradetried = FALSE;
5347  }
5348  }
5349  return SCIP_OKAY;
5350 }
5351 
5352 /** tighten lower bound */
5353 static
5355  SCIP* scip, /**< SCIP data structure */
5356  SCIP_CONS* cons, /**< linear constraint */
5357  int pos, /**< variable position */
5358  PROPRULE proprule, /**< propagation rule that deduced the value */
5359  SCIP_Real newlb, /**< new lower bound */
5360  SCIP_Real oldlb, /**< old lower bound */
5361  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5362  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5363  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5364  )
5365 {
5366  SCIP_CONSDATA* consdata;
5367  SCIP_VAR* var;
5368  SCIP_Real ub;
5369  SCIP_Bool infeasible;
5370  SCIP_Bool tightened;
5372  assert(cons != NULL);
5373  assert(!SCIPisInfinity(scip, newlb));
5374 
5375  consdata = SCIPconsGetData(cons);
5376  assert(consdata != NULL);
5377  var = consdata->vars[pos];
5378  assert(var != NULL);
5379 
5380  ub = SCIPvarGetUbLocal(var);
5381  newlb = SCIPadjustedVarLb(scip, var, newlb);
5382 
5383  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5384  {
5385  SCIP_VARTYPE vartype;
5386 
5387  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5388  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5389 
5390  vartype = SCIPvarGetType(var);
5391 
5392  /* tighten lower bound */
5393  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5394 
5395  if( infeasible )
5396  {
5397  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5398  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5399 
5400  /* analyze conflict */
5401  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5402 
5403  *cutoff = TRUE;
5404  }
5405  else if( tightened )
5406  {
5407  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5408  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5409  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5410 
5411  (*nchgbds)++;
5412 
5413  /* if variable type was changed we might be able to upgrade the constraint */
5414  if( vartype != SCIPvarGetType(var) )
5415  consdata->upgradetried = FALSE;
5416  }
5417  }
5418  return SCIP_OKAY;
5419 }
5420 
5421 /** tightens bounds of a single variable due to activity bounds (easy case) */
5422 static
5424  SCIP* scip, /**< SCIP data structure */
5425  SCIP_CONS* cons, /**< linear constraint */
5426  int pos, /**< position of the variable in the vars array */
5427  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5428  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5429  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5430  )
5431 {
5432  SCIP_CONSDATA* consdata;
5433  SCIP_VAR* var;
5434  SCIP_Real val;
5435  SCIP_Real lb;
5436  SCIP_Real ub;
5437  SCIP_Real lhs;
5438  SCIP_Real rhs;
5439 
5440  assert(scip != NULL);
5441  assert(cons != NULL);
5442  assert(cutoff != NULL);
5443  assert(nchgbds != NULL);
5444 
5445  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5446  if( SCIPconsIsModifiable(cons) )
5447  return SCIP_OKAY;
5448 
5449  consdata = SCIPconsGetData(cons);
5450  assert(consdata != NULL);
5451  assert(0 <= pos && pos < consdata->nvars);
5452 
5453  *cutoff = FALSE;
5454 
5455  var = consdata->vars[pos];
5456  assert(var != NULL);
5457 
5458  /* we cannot tighten bounds of multi-aggregated variables */
5460  return SCIP_OKAY;
5461 
5462  val = consdata->vals[pos];
5463  lhs = consdata->lhs;
5464  rhs = consdata->rhs;
5465  assert(!SCIPisZero(scip, val));
5466  assert(!SCIPisInfinity(scip, lhs));
5467  assert(!SCIPisInfinity(scip, -rhs));
5468 
5469  lb = SCIPvarGetLbLocal(var);
5470  ub = SCIPvarGetUbLocal(var);
5471  assert(SCIPisLE(scip, lb, ub));
5472 
5473  /* recompute activities if needed */
5474  if( !consdata->validactivities )
5475  consdataCalcActivities(scip, consdata);
5476  assert(consdata->validactivities);
5477  if( !consdata->validminact )
5478  consdataRecomputeMinactivity(scip, consdata);
5479  assert(consdata->validminact);
5480  if( !consdata->validmaxact )
5481  consdataRecomputeMaxactivity(scip, consdata);
5482  assert(consdata->validmaxact);
5483 
5484  if( val > 0.0 )
5485  {
5486  /* check, if we can tighten the variable's upper bound */
5487  if( !SCIPisInfinity(scip, rhs) )
5488  {
5489  SCIP_Real slack;
5490  SCIP_Real alpha;
5491 
5492  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5493  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5494  {
5495  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5496  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5497 
5498  *cutoff = TRUE;
5499  return SCIP_OKAY;
5500  }
5501 
5502  slack = rhs - consdata->minactivity;
5503 
5504  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5505  * it to zero
5506  */
5507  if( !SCIPisPositive(scip, slack) )
5508  slack = 0.0;
5509 
5510  alpha = val * (ub - lb);
5511  assert(!SCIPisNegative(scip, alpha));
5512 
5513  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5514  {
5515  SCIP_Real newub;
5516 
5517  /* compute new upper bound */
5518  newub = lb + (slack / val);
5519 
5520  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5521 
5522  if( *cutoff )
5523  {
5524  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5525  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5526 
5527  return SCIP_OKAY;
5528  }
5529 
5530  /* collect the new upper bound which is needed for the lower bound computation */
5531  ub = SCIPvarGetUbLocal(var);
5532  }
5533  }
5534 
5535  /* check, if we can tighten the variable's lower bound */
5536  if( !SCIPisInfinity(scip, -lhs) )
5537  {
5538  SCIP_Real slack;
5539  SCIP_Real alpha;
5540 
5541  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5542  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5543  {
5544  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5545  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5546 
5547  *cutoff = TRUE;
5548  return SCIP_OKAY;
5549  }
5550 
5551  slack = consdata->maxactivity - lhs;
5552 
5553  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5554  * it to zero
5555  */
5556  if( !SCIPisPositive(scip, slack) )
5557  slack = 0.0;
5558 
5559  alpha = val * (ub - lb);
5560  assert(!SCIPisNegative(scip, alpha));
5561 
5562  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5563  {
5564  SCIP_Real newlb;
5565 
5566  /* compute new lower bound */
5567  newlb = ub - (slack / val);
5568 
5569  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5570 
5571  if( *cutoff )
5572  {
5573  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5574  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5575 
5576  return SCIP_OKAY;
5577  }
5578  }
5579  }
5580  }
5581  else
5582  {
5583  /* check, if we can tighten the variable's lower bound */
5584  if( !SCIPisInfinity(scip, rhs) )
5585  {
5586  SCIP_Real slack;
5587  SCIP_Real alpha;
5588 
5589  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5590  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5591  {
5592  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5593  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5594 
5595  *cutoff = TRUE;
5596  return SCIP_OKAY;
5597  }
5598 
5599  slack = rhs - consdata->minactivity;
5600 
5601  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5602  * it to zero
5603  */
5604  if( !SCIPisPositive(scip, slack) )
5605  slack = 0.0;
5606 
5607  alpha = val * (lb - ub);
5608  assert(!SCIPisNegative(scip, alpha));
5609 
5610  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5611  {
5612  SCIP_Real newlb;
5613 
5614  /* compute new lower bound */
5615  newlb = ub + slack / val;
5616 
5617  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5618 
5619  if( *cutoff )
5620  {
5621  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5622  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5623 
5624  return SCIP_OKAY;
5625  }
5626  /* collect the new lower bound which is needed for the upper bound computation */
5627  lb = SCIPvarGetLbLocal(var);
5628  }
5629  }
5630 
5631  /* check, if we can tighten the variable's upper bound */
5632  if( !SCIPisInfinity(scip, -lhs) )
5633  {
5634  SCIP_Real slack;
5635  SCIP_Real alpha;
5636 
5637  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5638  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5639  {
5640  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5641  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5642 
5643  *cutoff = TRUE;
5644  return SCIP_OKAY;
5645  }
5646 
5647  slack = consdata->maxactivity - lhs;
5648 
5649  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5650  * it to zero
5651  */
5652  if( !SCIPisPositive(scip, slack) )
5653  slack = 0.0;
5654 
5655  alpha = val * (lb - ub);
5656  assert(!SCIPisNegative(scip, alpha));
5657 
5658  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5659  {
5660  SCIP_Real newub;
5661 
5662  /* compute new upper bound */
5663  newub = lb - (slack / val);
5664 
5665  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5666 
5667  if( *cutoff )
5668  {
5669  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5670  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5671 
5672  return SCIP_OKAY;
5673  }
5674  }
5675  }
5676  }
5677 
5678  return SCIP_OKAY;
5679 }
5680 
5681 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5682 static
5684  SCIP* scip, /**< SCIP data structure */
5685  SCIP_CONS* cons, /**< conflict detecting constraint */
5686  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5687  int nvars, /**< number of variables reasoning the infeasibility */
5688  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5689  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5690  )
5691 {
5692 #ifndef NDEBUG
5693  SCIP_CONSDATA* consdata;
5694 
5695  assert(scip != NULL);
5696  assert(cons != NULL);
5697 
5698  consdata = SCIPconsGetData(cons);
5699  assert(consdata != NULL);
5700  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5701 #endif
5702 
5703  /* conflict analysis can only be applied in solving stage and if it is turned on */
5705  return SCIP_OKAY;
5706 
5707  /* initialize conflict analysis */
5709 
5710  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5711  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5712 
5713  /* add reasoning variables to conflict candidate queue which led to the conflict */
5714  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5715 
5716  /* analyze the conflict */
5717  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5718 
5719  return SCIP_OKAY;
5720 }
5721 
5722 /** propagate ranged rows
5723  *
5724  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5725  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5726  * variables better.
5727  *
5728  * Example:
5729  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5730  *
5731  * x3 needs to be a multiple of 3, so the instance is infeasible.
5732  *
5733  * Example:
5734  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5735  *
5736  * The only possible value for x3 is 2, so the variable will be fixed.
5737  *
5738  * @todo add holes if possible
5739  */
5740 static
5742  SCIP* scip, /**< SCIP data structure */
5743  SCIP_CONS* cons, /**< linear constraint */
5744  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5745  int* nfixedvars, /**< pointer to count number of fixed variables */
5746  int* nchgbds, /**< pointer to count the number of bound changes */
5747  int* naddconss /**< pointer to count number of added constraints */
5748  )
5749 {
5750  SCIP_CONSHDLRDATA* conshdlrdata;
5751  SCIP_CONSHDLR* conshdlr;
5752  SCIP_CONSDATA* consdata;
5753  SCIP_VAR** infcheckvars;
5754  SCIP_Real* infcheckvals;
5755  SCIP_Real minactinfvars;
5756  SCIP_Real maxactinfvars;
5757  SCIP_Real lb;
5759  SCIP_Real feastol;
5760  SCIP_Real fixedact;
5761  SCIP_Real lhs;
5762  SCIP_Real rhs;
5763  SCIP_Real absminbincoef;
5764  SCIP_Longint gcd;
5765  SCIP_Longint gcdtmp;
5766  SCIP_Bool minactinfvarsinvalid;
5767  SCIP_Bool maxactinfvarsinvalid;
5768  SCIP_Bool possiblegcd;
5769  SCIP_Bool gcdisone;
5770  SCIP_Bool addartconss;
5771  int ninfcheckvars;
5772  int nunfixedvars;
5773  int nfixedconsvars;
5774  int ncontvars;
5775  int pos;
5776  int v;
5777 
5778  assert(scip != NULL);
5779  assert(cons != NULL);
5780  assert(cutoff != NULL);
5781  assert(nfixedvars != NULL);
5782  assert(nchgbds != NULL);
5783  assert(naddconss != NULL);
5784 
5785  /* modifiable constraint can be changed so we do not have all necessary information */
5786  if( SCIPconsIsModifiable(cons) )
5787  return SCIP_OKAY;
5788 
5789  consdata = SCIPconsGetData(cons);
5790  assert(consdata != NULL);
5791 
5792  /* we already did full ranged row propagation */
5793  if( consdata->rangedrowpropagated == 2 )
5794  return SCIP_OKAY;
5795 
5796  /* at least three variables are needed */
5797  if( consdata->nvars < 3 )
5798  return SCIP_OKAY;
5799 
5800  /* do nothing on normal inequalities */
5801  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5802  return SCIP_OKAY;
5803 
5804  /* get constraint handler data */
5805  conshdlr = SCIPconsGetHdlr(cons);
5806  assert(conshdlr != NULL);
5807  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5808  assert(conshdlrdata != NULL);
5809 
5810  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5811 
5812  /* we may add artificial constraints */
5813  if( addartconss )
5814  consdata->rangedrowpropagated = 2;
5815  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5816  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5817  * artificial constraints
5818  */
5819  else
5820  {
5821  if( consdata->rangedrowpropagated > 0 )
5822  return SCIP_OKAY;
5823 
5824  consdata->rangedrowpropagated = 1;
5825  }
5826  fixedact = 0;
5827  nfixedconsvars = 0;
5828  /* calculate fixed activity and number of fixed variables */
5829  for( v = consdata->nvars - 1; v >= 0; --v )
5830  {
5831  /* all zero coefficients should be eliminated */
5832  assert(!SCIPisZero(scip, consdata->vals[v]));
5833 
5834  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5835  {
5836  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5837  ++nfixedconsvars;
5838  }
5839  }
5840 
5841  /* do not work with huge fixed activities */
5842  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5843  return SCIP_OKAY;
5844 
5845  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5846  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5847  lhs = consdata->lhs - fixedact;
5848  rhs = consdata->rhs - fixedact;
5849  nunfixedvars = consdata->nvars - nfixedconsvars;
5850 
5851  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5852  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5853  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5854 
5855  absminbincoef = SCIP_REAL_MAX;
5856  ncontvars = 0;
5857  gcdisone = TRUE;
5858  possiblegcd = TRUE;
5859 
5860  /* we now partition all unfixed variables in two groups:
5861  *
5862  * the first one contains all integral variable with integral
5863  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5864  * given
5865  *
5866  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5867  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5868  */
5869 
5870  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5871  * variables
5872  */
5873  ninfcheckvars = 0;
5874  v = -1;
5875  pos = -1;
5876  do
5877  {
5878  ++v;
5879 
5880  /* partition the variables, do not change the order of collection, because it might be used later on */
5881  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5882  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5883  {
5884  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5885  {
5886  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5887  {
5888  ++ncontvars;
5889  }
5890  else if( SCIPvarIsBinary(consdata->vars[v]) )
5891  {
5892  SCIP_Real absval;
5893 
5894  absval = REALABS(consdata->vals[v]);
5895 
5896  if( absminbincoef > absval )
5897  absminbincoef = absval;
5898  }
5899 
5900  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5901  possiblegcd = FALSE;
5902  infcheckvars[ninfcheckvars] = consdata->vars[v];
5903  infcheckvals[ninfcheckvars] = consdata->vals[v];
5904  ++ninfcheckvars;
5905 
5906  if( pos == -1 )
5907  pos = v;
5908  }
5909  ++v;
5910  }
5911  }
5912  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5913 
5914  /* if the first group of variables is empty, we stop */
5915  /* @todo try to propagate/split up a constraint of the form:
5916  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5917  * 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]
5918  */
5919  if( v == consdata->nvars )
5920  goto TERMINATE;
5921 
5922  /* we need at least two non-continuous variables */
5923  if( ncontvars + 2 > nunfixedvars )
5924  goto TERMINATE;
5925 
5926  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5927  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5928 
5929  feastol = SCIPfeastol(scip);
5930 
5931  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5932  assert(gcd >= 2);
5933 
5934  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5935  * calculate gcd over the first part of variables */
5936  for( ; v < consdata->nvars; ++v )
5937  {
5938  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5939  continue;
5940 
5941  if( SCIPvarIsBinary(consdata->vars[v]) )
5942  {
5943  SCIP_Real absval;
5944 
5945  absval = REALABS(consdata->vals[v]);
5946 
5947  if( absminbincoef > absval )
5948  absminbincoef = absval;
5949  }
5950 
5951  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5952  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5953  {
5954  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5955  ++ncontvars;
5956 
5957  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5958  possiblegcd = FALSE;
5959  infcheckvars[ninfcheckvars] = consdata->vars[v];
5960  infcheckvals[ninfcheckvars] = consdata->vals[v];
5961 
5962  ++ninfcheckvars;
5963 
5964  if( pos == -1 )
5965  pos = v;
5966  }
5967  else
5968  {
5969  assert(REALABS(consdata->vals[v]) > 1.5);
5970 
5971  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5972  assert(gcdtmp >= 1);
5973 
5974  if( gcdtmp == 1 )
5975  {
5976  infcheckvars[ninfcheckvars] = consdata->vars[v];
5977  infcheckvals[ninfcheckvars] = consdata->vals[v];
5978 
5979  ++ninfcheckvars;
5980 
5981  if( pos == -1 )
5982  pos = v;
5983  }
5984  else
5985  gcd = gcdtmp;
5986  }
5987  }
5988  assert(gcd >= 2);
5989 
5990  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5991  * normalizeCons() */
5992  if( ninfcheckvars == 0 )
5993  goto TERMINATE;
5994 
5995  assert(pos >= 0);
5996 
5997  minactinfvarsinvalid = FALSE;
5998  maxactinfvarsinvalid = FALSE;
5999  maxactinfvars = 0.0;
6000  minactinfvars = 0.0;
6001 
6002  /* calculate activities over all infcheckvars */
6003  for( v = ninfcheckvars - 1; v >= 0; --v )
6004  {
6005  lb = SCIPvarGetLbLocal(infcheckvars[v]);
6006  ub = SCIPvarGetUbLocal(infcheckvars[v]);
6007 
6008  if( SCIPisInfinity(scip, -lb) )
6009  {
6010  if( infcheckvals[v] < 0.0 )
6011  maxactinfvarsinvalid = TRUE;
6012  else
6013  minactinfvarsinvalid = TRUE;
6014  }
6015  else
6016  {
6017  if( infcheckvals[v] < 0.0 )
6018  maxactinfvars += infcheckvals[v] * lb;
6019  else
6020  minactinfvars += infcheckvals[v] * lb;
6021  }
6022 
6023  if( SCIPisInfinity(scip, ub) )
6024  {
6025  if( infcheckvals[v] > 0.0 )
6026  maxactinfvarsinvalid = TRUE;
6027  else
6028  minactinfvarsinvalid = TRUE;
6029  }
6030  else
6031  {
6032  if( infcheckvals[v] > 0.0 )
6033  maxactinfvars += infcheckvals[v] * ub;
6034  else
6035  minactinfvars += infcheckvals[v] * ub;
6036  }
6037 
6038  /* better abort on to big values */
6039  if( SCIPisHugeValue(scip, -minactinfvars) )
6040  minactinfvarsinvalid = TRUE;
6041  if( SCIPisHugeValue(scip, maxactinfvars) )
6042  maxactinfvarsinvalid = TRUE;
6043 
6044  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6045  goto TERMINATE;
6046  }
6047  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6048 
6049  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6050  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6051 
6052  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6053  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6054  * activities */
6055  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6056  * !!!note!!!
6057  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6058  * are not at their global bound
6059  */
6060 
6061  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6062  * infeasibility */
6063  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6064  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6065  {
6066  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6067  SCIPdebugPrintCons(scip, cons, NULL);
6068 
6069  /* start conflict analysis */
6070  /* @todo improve conflict analysis by adding relaxed bounds */
6071  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6072 
6073  *cutoff = TRUE;
6074  }
6075  else if( ncontvars == 0 )
6076  {
6077  SCIP_Longint gcdinfvars = -1;
6078 
6079  /* check for gcd over all infcheckvars */
6080  if( possiblegcd )
6081  {
6082  v = ninfcheckvars - 1;
6083  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6084  assert(gcdinfvars >= 2);
6085 
6086  for( ; v >= 0 && gcdinfvars >= 2; --v )
6087  {
6088  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6089  }
6090  }
6091  else if( gcdisone )
6092  gcdinfvars = 1;
6093 
6094  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6095 
6096  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6097  if( gcdinfvars >= 1 )
6098  {
6099  SCIP_Real value;
6100  SCIP_Real value2;
6101  SCIP_Real minvalue = SCIP_INVALID;
6102  SCIP_Real maxvalue = SCIP_INVALID;
6103  int nsols = 0;
6104 
6105  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6106 
6107  /* check how many possible solutions exist */
6108  while( SCIPisLE(scip, value, maxactinfvars) )
6109  {
6110  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6111 
6112  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6113  {
6114  ++nsols;
6115 
6116  /* early termination if we found more than two solutions */
6117  if( nsols == 3 )
6118  break;
6119 
6120  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6121  minvalue = value;
6122 
6123  maxvalue = value;
6124  }
6125  value += gcdinfvars;
6126  }
6127  assert(nsols < 2 || minvalue <= maxvalue);
6128 
6129  /* determine last possible solution for better bounding */
6130  if( nsols == 3 )
6131  {
6132 #ifndef NDEBUG
6133  SCIP_Real secondsolval = maxvalue;
6134 #endif
6135  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6136 
6137  /* check how many possible solutions exist */
6138  while( SCIPisGE(scip, value, minactinfvars) )
6139  {
6140  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6141 
6142  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6143  {
6144  maxvalue = value;
6145  assert(maxvalue > minvalue);
6146  break;
6147  }
6148  value -= gcdinfvars;
6149  }
6150  assert(maxvalue > secondsolval);
6151  }
6152 
6153  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6154  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6155 
6156  /* no possible solution found */
6157  if( nsols == 0 )
6158  {
6159  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6160  gcdinfvars, gcd, lhs, rhs);
6161  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6162  SCIPdebugPrintCons(scip, cons, NULL);
6163 
6164  /* start conflict analysis */
6165  /* @todo improve conflict analysis by adding relaxed bounds */
6166  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6167 
6168  *cutoff = TRUE;
6169  }
6170  /* if only one solution exist we can extract a new constraint or fix variables */
6171  else if( nsols == 1 )
6172  {
6173  assert(minvalue == maxvalue); /*lint !e777*/
6174 
6175  /* we can fix the only variable in our second set of variables */
6176  if( ninfcheckvars == 1 )
6177  {
6178  SCIP_Bool fixed;
6179 
6180  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6181 
6182  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6183  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6184  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6185 
6186  /* fix variable to only possible value */
6187  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6188  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6189 
6190  if( *cutoff )
6191  {
6192  /* start conflict analysis */
6193  /* @todo improve conflict analysis by adding relaxed bounds */
6194  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6195  }
6196 
6197  if( fixed )
6198  ++(*nfixedvars);
6199  }
6200  else
6201  {
6202  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6203  if( ninfcheckvars == nunfixedvars - 1 )
6204  {
6205  SCIP_Real bound;
6206  SCIP_Bool foundvar = FALSE;
6207  SCIP_Bool fixed;
6208  int w = 0;
6209 
6210  assert(ninfcheckvars > 0);
6211 
6212  /* find variable which is not an infcheckvar and fix it */
6213  for( v = 0; v < consdata->nvars - 1; ++v )
6214  {
6215  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6216  {
6217  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6218  {
6219 #ifndef NDEBUG
6220  int v2 = v + 1;
6221  int w2 = w;
6222 
6223  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6224 
6225  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6226  {
6227  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6228  continue;
6229 
6230  assert(consdata->vars[v2] == infcheckvars[w2]);
6231  ++w2;
6232  }
6233  assert(w2 == ninfcheckvars);
6234 #endif
6235  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6236 
6237  foundvar = TRUE;
6238 
6239  if( consdata->vals[v] < 0 )
6240  {
6241  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6242  }
6243  else
6244  {
6245  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6246  }
6247 
6248  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6249  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6250  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6251 
6252  /* fix variable to only possible value */
6253  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6254  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6255 
6256  if( *cutoff )
6257  {
6258  /* start conflict analysis */
6259  /* @todo improve conflict analysis by adding relaxed bounds */
6260  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6261  consdata->vars[v], bound) );
6262  }
6263 
6264  if( fixed )
6265  ++(*nfixedvars);
6266 
6267  break;
6268  }
6269 
6270  ++w;
6271  }
6272  }
6273 
6274  /* maybe last variable was the not infcheckvar */
6275  if( !foundvar )
6276  {
6277  assert(v == consdata->nvars - 1);
6278  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6279 
6280  if( consdata->vals[v] < 0 )
6281  {
6282  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6283  }
6284  else
6285  {
6286  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6287  }
6288 
6289  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6290  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6291  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6292 
6293  /* fix variable to only possible value */
6294  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6295  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6296 
6297  if( *cutoff )
6298  {
6299  /* start conflict analysis */
6300  /* @todo improve conflict analysis by adding relaxed bounds */
6301  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6302  consdata->vars[v], bound) );
6303  }
6304 
6305  if( fixed )
6306  ++(*nfixedvars);
6307  }
6308  }
6309  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6310  {
6311  /* aggregation possible if we have two variables, but this will be done later on */
6312  SCIP_CONS* newcons;
6313  char name[SCIP_MAXSTRLEN];
6314 
6315  /* create, add, and release new artificial constraint */
6316  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6317  ++conshdlrdata->naddconss;
6318 
6319  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6320 
6321  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6322  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6323  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6324 
6325  SCIPdebugPrintCons(scip, newcons, NULL);
6326 
6327  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6328 
6329  ++(*naddconss);
6330  }
6331  }
6332  }
6333  /* at least two solutions */
6334  else
6335  {
6336  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6337 
6338  /* only one variable in the second set, so we can bound this variables */
6339  if( ninfcheckvars == 1 )
6340  {
6341  SCIP_Bool tightened;
6342  SCIP_Real newlb;
6343  SCIP_Real newub;
6344 
6345  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6346 
6347  if( infcheckvals[0] < 0 )
6348  {
6349  newlb = maxvalue/infcheckvals[0];
6350  newub = minvalue/infcheckvals[0];
6351  }
6352  else
6353  {
6354  newlb = minvalue/infcheckvals[0];
6355  newub = maxvalue/infcheckvals[0];
6356  }
6357  assert(newlb < newub);
6358 
6359  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6360  {
6361  /* update lower bound of variable */
6362  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6363  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6364 
6365  /* tighten variable lower bound to minimal possible value */
6366  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6367  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6368 
6369  if( *cutoff )
6370  {
6371  /* start conflict analysis */
6372  /* @todo improve conflict analysis by adding relaxed bounds */
6373  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6374  }
6375 
6376  if( tightened )
6377  ++(*nchgbds);
6378  }
6379 
6380  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6381  {
6382  /* update upper bound of variable */
6383  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6384  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6385 
6386  /* tighten variable upper bound to maximal possible value */
6387  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6388  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6389 
6390  if( *cutoff )
6391  {
6392  /* start conflict analysis */
6393  /* @todo improve conflict analysis by adding relaxed bounds */
6394  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6395  }
6396 
6397  if( tightened )
6398  ++(*nchgbds);
6399  }
6400  }
6401  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6402  else if( ninfcheckvars == nunfixedvars - 1 )
6403  {
6404  SCIP_Bool foundvar = FALSE;
6405  SCIP_Bool tightened;
6406  SCIP_Real newlb;
6407  SCIP_Real newub;
6408  int w = 0;
6409 
6410  assert(ninfcheckvars > 0);
6411  assert(minvalue < maxvalue);
6412 
6413  /* find variable which is not an infcheckvar and fix it */
6414  for( v = 0; v < consdata->nvars - 1; ++v )
6415  {
6416  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6417  {
6418  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6419  {
6420 #ifndef NDEBUG
6421  int v2 = v + 1;
6422  int w2 = w;
6423 
6424  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6425 
6426  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6427  {
6428  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6429  continue;
6430 
6431  assert(consdata->vars[v2] == infcheckvars[w2]);
6432  ++w2;
6433  }
6434  assert(w2 == ninfcheckvars);
6435 #endif
6436 
6437  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6438  foundvar = TRUE;
6439 
6440  if( consdata->vals[v] < 0 )
6441  {
6442  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6443  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6444  }
6445  else
6446  {
6447  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6448  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6449  }
6450  assert(SCIPisLE(scip, newlb, newub));
6451 
6452  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6453  {
6454  /* update lower bound of variable */
6455  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6456  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6457 
6458  /* tighten variable lower bound to minimal possible value */
6459  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6460  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6461 
6462  if( *cutoff )
6463  {
6464  /* start conflict analysis */
6465  /* @todo improve conflict analysis by adding relaxed bounds */
6466  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6467  consdata->vars[v], newlb) );
6468  }
6469 
6470  if( tightened )
6471  ++(*nchgbds);
6472  }
6473 
6474  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6475  {
6476  /* update upper bound of variable */
6477  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6478  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6479 
6480  /* tighten variable upper bound to maximal possible value */
6481  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6482  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6483 
6484  if( *cutoff )
6485  {
6486  /* start conflict analysis */
6487  /* @todo improve conflict analysis by adding relaxed bounds */
6488  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6489  consdata->vars[v], newub) );
6490  }
6491 
6492  if( tightened )
6493  ++(*nchgbds);
6494  }
6495 
6496  break;
6497  }
6498 
6499  ++w;
6500  }
6501  }
6502 
6503  /* maybe last variable was the not infcheckvar */
6504  if( !foundvar )
6505  {
6506  assert(v == consdata->nvars - 1);
6507  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6508 
6509  if( consdata->vals[v] < 0 )
6510  {
6511  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6512  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6513  }
6514  else
6515  {
6516  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6517  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6518  }
6519  assert(SCIPisLE(scip, newlb, newub));
6520 
6521  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6522  {
6523  /* update lower bound of variable */
6524  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6525  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6526 
6527  /* tighten variable lower bound to minimal possible value */
6528  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6529  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6530 
6531  if( *cutoff )
6532  {
6533  /* start conflict analysis */
6534  /* @todo improve conflict analysis by adding relaxed bounds */
6535  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6536  }
6537 
6538  if( tightened )
6539  ++(*nchgbds);
6540  }
6541 
6542  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6543  {
6544  /* update upper bound of variable */
6545  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6546  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6547 
6548  /* tighten variable upper bound to maximal possible value */
6549  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6550  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6551 
6552  if( *cutoff )
6553  {
6554  /* start conflict analysis */
6555  /* @todo improve conflict analysis by adding relaxed bounds */
6556  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6557  }
6558 
6559  if( tightened )
6560  ++(*nchgbds);
6561  }
6562  }
6563  }
6564  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6565  * region for our infcheckvars, if possible
6566  */
6567  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6568  {
6569  SCIP_CONS* newcons;
6570  char name[SCIP_MAXSTRLEN];
6571  SCIP_Real newlhs;
6572  SCIP_Real newrhs;
6573 
6574  assert(maxvalue > minvalue);
6575 
6576  if( SCIPisGT(scip, minvalue, minactinfvars) )
6577  newlhs = minvalue;
6578  else
6579  newlhs = -SCIPinfinity(scip);
6580 
6581  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6582  newrhs = maxvalue;
6583  else
6584  newrhs = SCIPinfinity(scip);
6585 
6586  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6587  {
6588  /* create, add, and release new artificial constraint */
6589  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6590  ++conshdlrdata->naddconss;
6591 
6592  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6593 
6594  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6595  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6596  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6597 
6598  SCIPdebugPrintCons(scip, newcons, NULL);
6599  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6600 
6601  ++(*naddconss);
6602  }
6603  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6604  * should be maxvalue */
6605  }
6606  }
6607  }
6608  }
6609  else if( addartconss && ncontvars < ninfcheckvars )
6610  {
6611  SCIP_Real maxact = 0.0;
6612  SCIP_Real minact = 0.0;
6613  int w = 0;
6614 
6615  /* compute activities of non-infcheckvars */
6616  for( v = 0; v < consdata->nvars; ++v )
6617  {
6618  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6619  {
6620  ++w;
6621  continue;
6622  }
6623 
6624  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6625  {
6626  if( SCIPvarIsBinary(consdata->vars[v]) )
6627  {
6628  if( consdata->vals[v] > 0.0 )
6629  maxact += consdata->vals[v];
6630  else
6631  minact += consdata->vals[v];
6632  }
6633  else
6634  {
6635  SCIP_Real tmpval;
6636 
6637  assert(SCIPvarIsIntegral(consdata->vars[v]));
6638 
6639  if( consdata->vals[v] > 0.0 )
6640  {
6641  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6642 
6643  if( SCIPisHugeValue(scip, -tmpval) )
6644  break;
6645 
6646  minact += tmpval;
6647 
6648  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6649 
6650  if( SCIPisHugeValue(scip, tmpval) )
6651  break;
6652 
6653  maxact += tmpval;
6654  }
6655  else
6656  {
6657  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6658 
6659  if( SCIPisHugeValue(scip, -tmpval) )
6660  break;
6661 
6662  minact += tmpval;
6663 
6664  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6665 
6666  if( SCIPisHugeValue(scip, tmpval) )
6667  break;
6668 
6669  maxact += tmpval;
6670  }
6671  }
6672  }
6673  }
6674  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6675  {
6676  SCIP_CONS* newcons;
6677  char name[SCIP_MAXSTRLEN];
6678  SCIP_Real newlhs;
6679  SCIP_Real newrhs;
6680 
6681  assert(maxact > minact);
6682  assert(w == ninfcheckvars);
6683 
6684  newlhs = lhs - maxact;
6685  newrhs = rhs - minact;
6686  assert(newlhs < newrhs);
6687 
6688  /* create, add, and release new artificial constraint */
6689  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6690  ++conshdlrdata->naddconss;
6691 
6692  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6693 
6694  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6695  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6696  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6697 
6698  SCIPdebugPrintCons(scip, newcons, NULL);
6699  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6700 
6701  ++(*naddconss);
6702  }
6703  }
6704 
6705  TERMINATE:
6706  SCIPfreeBufferArray(scip, &infcheckvals);
6707  SCIPfreeBufferArray(scip, &infcheckvars);
6708 
6709  return SCIP_OKAY;
6710 }
6711 
6712 /** tightens bounds of a single variable due to activity bounds */
6713 static
6715  SCIP* scip, /**< SCIP data structure */
6716  SCIP_CONS* cons, /**< linear constraint */
6717  int pos, /**< position of the variable in the vars array */
6718  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6719  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6720  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6721  )
6722 {
6723  SCIP_CONSDATA* consdata;
6724  SCIP_VAR* var;
6725  SCIP_Real val;
6726  SCIP_Real lb;
6727  SCIP_Real ub;
6728  SCIP_Real minresactivity;
6729  SCIP_Real maxresactivity;
6730  SCIP_Real lhs;
6732  SCIP_Bool infeasible;
6733  SCIP_Bool tightened;
6734  SCIP_Bool minisrelax;
6735  SCIP_Bool maxisrelax;
6736  SCIP_Bool isminsettoinfinity;
6737  SCIP_Bool ismaxsettoinfinity;
6738 
6739  assert(scip != NULL);
6740  assert(cons != NULL);
6741  assert(cutoff != NULL);
6742  assert(nchgbds != NULL);
6743 
6744  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6745  if( SCIPconsIsModifiable(cons) )
6746  return SCIP_OKAY;
6747 
6748  consdata = SCIPconsGetData(cons);
6749  assert(consdata != NULL);
6750  assert(0 <= pos && pos < consdata->nvars);
6751 
6752  *cutoff = FALSE;
6753 
6754  var = consdata->vars[pos];
6755 
6756  /* we cannot tighten bounds of multi-aggregated variables */
6758  return SCIP_OKAY;
6759 
6760  val = consdata->vals[pos];
6761  lhs = consdata->lhs;
6762  rhs = consdata->rhs;
6763  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6764  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6765  assert(var != NULL);
6766  assert(!SCIPisZero(scip, val));
6767  assert(!SCIPisInfinity(scip, lhs));
6768  assert(!SCIPisInfinity(scip, -rhs));
6769 
6770  lb = SCIPvarGetLbLocal(var);
6771  ub = SCIPvarGetUbLocal(var);
6772  assert(SCIPisLE(scip, lb, ub));
6773 
6774  if( val > 0.0 )
6775  {
6776  /* check, if we can tighten the variable's bounds */
6777  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6778  {
6779  SCIP_Real newub;
6780 
6781  newub = (rhs - minresactivity)/val;
6782 
6783  if( !SCIPisInfinity(scip, newub) &&
6784  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6785  {
6786  SCIP_Bool activityunreliable;
6787  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6788 
6789  /* check minresactivities for reliability */
6790  if( activityunreliable )
6791  {
6792  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6793  newub = (rhs - minresactivity)/val;
6794  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6795  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6796  && (!force || !SCIPisLT(scip, newub, ub)));
6797  }
6798 
6799  if( !activityunreliable )
6800  {
6801  /* tighten upper bound */
6802  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6803  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6804  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6805  &infeasible, &tightened) );
6806  if( infeasible )
6807  {
6808  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6809  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6810 
6811  /* analyze conflict */
6812  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6813 
6814  *cutoff = TRUE;
6815  return SCIP_OKAY;
6816  }
6817  if( tightened )
6818  {
6819  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6820  assert(SCIPisFeasLE(scip, ub, newub));
6821  (*nchgbds)++;
6822 
6823  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6824  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6825  }
6826  }
6827  }
6828  }
6829 
6830  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6831  {
6832  SCIP_Real newlb;
6833 
6834  newlb = (lhs - maxresactivity)/val;
6835  if( !SCIPisInfinity(scip, -newlb) &&
6836  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6837  {
6838  /* check maxresactivities for reliability */
6839  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6840  {
6841  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6842  newlb = (lhs - maxresactivity)/val;
6843 
6844  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6845  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6846  && (!force || !SCIPisGT(scip, newlb, lb))) )
6847  return SCIP_OKAY;
6848  }
6849 
6850  /* tighten lower bound */
6851  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6852  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6853  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6854  &infeasible, &tightened) );
6855  if( infeasible )
6856  {
6857  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6858  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6859 
6860  /* analyze conflict */
6861  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6862 
6863  *cutoff = TRUE;
6864  return SCIP_OKAY;
6865  }
6866  if( tightened )
6867  {
6868  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6869  assert(SCIPisFeasGE(scip, lb, newlb));
6870  (*nchgbds)++;
6871  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6872  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6873  }
6874  }
6875  }
6876  }
6877  else
6878  {
6879  /* check, if we can tighten the variable's bounds */
6880  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6881  {
6882  SCIP_Real newlb;
6883 
6884  newlb = (rhs - minresactivity)/val;
6885  if( !SCIPisInfinity(scip, -newlb) &&
6886  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6887  {
6888  SCIP_Bool activityunreliable;
6889  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6890  /* check minresactivities for reliability */
6891  if( activityunreliable )
6892  {
6893  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6894  newlb = (rhs - minresactivity)/val;
6895 
6896  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6897  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6898  && (!force || !SCIPisGT(scip, newlb, lb)));
6899  }
6900 
6901  if( !activityunreliable )
6902  {
6903  /* tighten lower bound */
6904  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6905  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6906  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6907  &infeasible, &tightened) );
6908  if( infeasible )
6909  {
6910  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6911  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6912 
6913  /* analyze conflict */
6914  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6915 
6916  *cutoff = TRUE;
6917  return SCIP_OKAY;
6918  }
6919  if( tightened )
6920  {
6921  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6922  assert(SCIPisFeasGE(scip, lb, newlb));
6923  (*nchgbds)++;
6924  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6925  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6926  }
6927  }
6928  }
6929  }
6930 
6931  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6932  {
6933  SCIP_Real newub;
6934 
6935  newub = (lhs - maxresactivity)/val;
6936  if( !SCIPisInfinity(scip, newub) &&
6937  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6938  {
6939  /* check maxresactivities for reliability */
6940  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6941  {
6942  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6943  newub = (lhs - maxresactivity)/val;
6944 
6945  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6946  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6947  && (!force || !SCIPisLT(scip, newub, ub))) )
6948  return SCIP_OKAY;
6949  }
6950 
6951  /* tighten upper bound */
6952  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6953  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6954  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6955  &infeasible, &tightened) );
6956  if( infeasible )
6957  {
6958  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6959  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6960 
6961  /* analyze conflict */
6962  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6963 
6964  *cutoff = TRUE;
6965  return SCIP_OKAY;
6966  }
6967  if( tightened )
6968  {
6969  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6970  assert(SCIPisFeasLE(scip, ub, newub));
6971  (*nchgbds)++;
6972  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6973  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6974  }
6975  }
6976  }
6977  }
6978 
6979  return SCIP_OKAY;
6980 }
6981 
6982 #define MAXTIGHTENROUNDS 10
6983 
6984 /** tightens bounds of variables in constraint due to activity bounds */
6985 static
6987  SCIP* scip, /**< SCIP data structure */
6988  SCIP_CONS* cons, /**< linear constraint */
6989  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6990  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6991  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6992  int* nchgbds /**< pointer to count the total number of tightened bounds */
6993  )
6994 {
6995  SCIP_CONSDATA* consdata;
6996  unsigned int tightenmode;
6997  int nvars;
6998  int nrounds;
6999  int lastchange;
7000  int oldnchgbds;
7001 #ifndef SCIP_DEBUG
7002  int oldnchgbdstotal;
7003 #endif
7004  int v;
7005  SCIP_Bool force;
7006  SCIP_Bool easycase;
7007 
7008  assert(scip != NULL);
7009  assert(cons != NULL);
7010  assert(nchgbds != NULL);
7011  assert(cutoff != NULL);
7012 
7013  *cutoff = FALSE;
7014 
7015  /* we cannot tighten variables' bounds, if the constraint may be not complete */
7016  if( SCIPconsIsModifiable(cons) )
7017  return SCIP_OKAY;
7018 
7019  /* if a constraint was created after presolve, then it may hold fixed variables
7020  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7021  * thus, ensure here again that variable fixings have been applied
7022  */
7023  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7024  if( *cutoff )
7025  return SCIP_OKAY;
7026 
7027  /* check if constraint has any chances of tightening bounds */
7028  if( !canTightenBounds(scip, cons) )
7029  return SCIP_OKAY;
7030 
7031  consdata = SCIPconsGetData(cons);
7032  assert(consdata != NULL);
7033 
7034  nvars = consdata->nvars;
7035  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7036 
7037  /* we are at the root node or during presolving */
7038  if( SCIPgetDepth(scip) < 1 )
7039  tightenmode = 2;
7040  else
7041  tightenmode = 1;
7042 
7043  /* stop if we already tightened the constraint and the tightening is not forced */
7044  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7045  return SCIP_OKAY;
7046 
7047  /* ensure that the variables are properly sorted */
7048  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
7049  {
7050  SCIP_CALL( consdataSort(scip, consdata) );
7051  assert(consdata->binvarssorted);
7052  }
7053 
7054  /* update maximal activity delta if necessary */
7055  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7056  consdataRecomputeMaxActivityDelta(scip, consdata);
7057 
7058  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7059  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7060  checkMaxActivityDelta(scip, consdata);
7061 
7062  /* this may happen if all variables are fixed */
7063  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7064  return SCIP_OKAY;
7065 
7066  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7067  {
7068  SCIP_Real slack;
7069  SCIP_Real surplus;
7070  SCIP_Real minactivity;
7071  SCIP_Real maxactivity;
7072  SCIP_Bool minisrelax;
7073  SCIP_Bool maxisrelax;
7074 
7075  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7076  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
7077  assert(!SCIPisInfinity(scip, minactivity));
7078  assert(!SCIPisInfinity(scip, -maxactivity));
7079 
7080  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7081  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7082 
7083  /* check if the constraint will propagate */
7084  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7085  return SCIP_OKAY;
7086  }
7087 
7088  /* check if we can use fast implementation for easy and numerically well behaved cases */
7089  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7090 
7091  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7092  lastchange = -1;
7093  oldnchgbds = 0;
7094 
7095 #ifndef SCIP_DEBUG
7096  oldnchgbdstotal = *nchgbds;
7097 #endif
7098 
7099  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7100  {
7101  /* mark the constraint to have the variables' bounds tightened */
7102  consdata->boundstightened = (unsigned int)tightenmode;
7103 
7104  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7105  * sorting enables skipping variables
7106  */
7107  v = 0;
7108  while( v < nvars && v != lastchange && !(*cutoff) )
7109  {
7110  oldnchgbds = *nchgbds;
7111 
7112  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
7113 
7114  if( easycase )
7115  {
7116  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7117  }
7118  else
7119  {
7120  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7121  }
7122 
7123  /* if there was no progress, skip the rest of the binary variables */
7124  if( *nchgbds > oldnchgbds )
7125  {
7126  lastchange = v;
7127  ++v;
7128  }
7129  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
7130  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7131  v = consdata->nbinvars;
7132  else
7133  ++v;
7134  }
7135 
7136 #ifndef SCIP_DEBUG
7137  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7138  *nchgbds - oldnchgbdstotal, nrounds);
7139  oldnchgbdstotal += oldnchgbds;
7140 #endif
7141  }
7142 
7143 #ifndef NDEBUG
7144  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7145  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7146 #endif
7147 
7148  return SCIP_OKAY;
7149 }
7150 
7151 /** checks linear constraint for feasibility of given solution or current solution */
7152 static
7154  SCIP* scip, /**< SCIP data structure */
7155  SCIP_CONS* cons, /**< linear constraint */
7156  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7157  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7158  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7159  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7160  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7161  )
7162 {
7163  SCIP_CONSDATA* consdata;
7164  SCIP_Real activity;
7165  SCIP_Real absviol;
7166  SCIP_Real relviol;
7167  SCIP_Real lhsviol;
7168  SCIP_Real rhsviol;
7169 
7170  assert(scip != NULL);
7171  assert(cons != NULL);
7172  assert(violated != NULL);
7173 
7174  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7175  SCIPdebugPrintCons(scip, cons, NULL);
7176 
7177  consdata = SCIPconsGetData(cons);
7178  assert(consdata != NULL);
7179 
7180  *violated = FALSE;
7181 
7182  if( consdata->row != NULL )
7183  {
7184  if( !checklprows && SCIProwIsInLP(consdata->row) )
7185  return SCIP_OKAY;
7186  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7187  activity = consdataComputePseudoActivity(scip, consdata);
7188  else
7189  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7190  }
7191  else
7192  activity = consdataGetActivity(scip, consdata, sol);
7193 
7194  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7195  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7196  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7197  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7198 
7199  /* calculate absolute and relative bound violations */
7200  lhsviol = consdata->lhs - activity;
7201  rhsviol = activity - consdata->rhs;
7202 
7203  absviol = 0.0;
7204  relviol = 0.0;
7205  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7206  {
7207  absviol = lhsviol;
7208  relviol = SCIPrelDiff(consdata->lhs, activity);
7209  }
7210  else if( rhsviol > 0 )
7211  {
7212  absviol = rhsviol;
7213  relviol = SCIPrelDiff(activity, consdata->rhs);
7214  }
7215 
7216  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7217  * return infeasible for safety
7218  */
7219  if( activity == SCIP_INVALID ) /*lint !e777*/
7220  {
7221  assert(sol == NULL);
7222  *violated = TRUE;
7223 
7224  /* set violation of invalid pseudo solutions */
7225  absviol = SCIP_INVALID;
7226  relviol = SCIP_INVALID;
7227 
7228  /* reset constraint age since we are in enforcement */
7229  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7230  }
7231  /* check with relative tolerances (the default) */
7232  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7233  {
7234  /* the "normal" check: one of the two sides is violated */
7235  if( !checkrelmaxabs )
7236  {
7237  *violated = TRUE;
7238 
7239  /* only reset constraint age if we are in enforcement */
7240  if( sol == NULL )
7241  {
7242  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7243  }
7244  }
7245  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7246  * small compared to the absolute values occurring in the activity
7247  */
7248  else
7249  {
7250  SCIP_Real maxabs;
7251  SCIP_Real coef;
7252  SCIP_Real absval;
7253  SCIP_Real solval;
7254  int v;
7255 
7256  maxabs = 1.0;
7257 
7258  /* compute maximum absolute value */
7259  for( v = 0; v < consdata->nvars; ++v )
7260  {
7261  if( consdata->vals != NULL )
7262  {
7263  coef = consdata->vals[v];
7264  }
7265  else
7266  coef = 1.0;
7267 
7268  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7269  absval = REALABS( coef * solval );
7270  maxabs = MAX( maxabs, absval );
7271  }
7272 
7273  /* regard left hand side, first */
7274  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7275  {
7276  /* check whether violation is random noise */
7277  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7278  {
7279  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7280  consdata->lhs - activity, maxabs);
7281  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7282 
7283  /* only increase constraint age if we are in enforcement */
7284  if( sol == NULL )
7285  {
7286  SCIP_CALL( SCIPincConsAge(scip, cons) );
7287  }
7288  }
7289  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7290  else if( SCIPisZero(scip, consdata->lhs) )
7291  {
7292  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7293  {
7294  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7295  consdata->lhs - activity, maxabs);
7296  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7297 
7298  /* only increase constraint age if we are in enforcement */
7299  if( sol == NULL )
7300  {
7301  SCIP_CALL( SCIPincConsAge(scip, cons) );
7302  }
7303  }
7304  else
7305  {
7306  *violated = TRUE;
7307 
7308  /* only reset constraint age if we are in enforcement */
7309  if( sol == NULL )
7310  {
7311  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7312  }
7313  }
7314  }
7315  else
7316  {
7317  *violated = TRUE;
7318 
7319  /* only reset constraint age if we are in enforcement */
7320  if( sol == NULL )
7321  {
7322  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7323  }
7324  }
7325  }
7326 
7327  /* now regard right hand side */
7328  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7329  {
7330  /* check whether violation is random noise */
7331  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7332  {
7333  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7334  activity - consdata->rhs, maxabs);
7335  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7336 
7337  /* only increase constraint age if we are in enforcement */
7338  if( sol == NULL )
7339  {
7340  SCIP_CALL( SCIPincConsAge(scip, cons) );
7341  }
7342  }
7343  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7344  else if( SCIPisZero(scip, consdata->rhs) )
7345  {
7346  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7347  {
7348  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7349  activity - consdata->rhs, maxabs);
7350  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7351 
7352  /* only increase constraint age if we are in enforcement */
7353  if( sol == NULL )
7354  {
7355  SCIP_CALL( SCIPincConsAge(scip, cons) );
7356  }
7357  }
7358  else
7359  {
7360  *violated = TRUE;
7361 
7362  /* only reset constraint age if we are in enforcement */
7363  if( sol == NULL )
7364  {
7365  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7366  }
7367  }
7368  }
7369  else
7370  {
7371  *violated = TRUE;
7372 
7373  /* only reset constraint age if we are in enforcement */
7374  if( sol == NULL )
7375  {
7376  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7377  }
7378  }
7379  }
7380  }
7381  }
7382  /* check with absolute tolerances */
7383  else if( consdata->checkabsolute &&
7384  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7385  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7386  {
7387  *violated = TRUE;
7388 
7389  /* only reset constraint age if we are in enforcement */
7390  if( sol == NULL )
7391  {
7392  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7393  }
7394  }
7395  else
7396  {
7397  /* only increase constraint age if we are in enforcement */
7398  if( sol == NULL )
7399  {
7400  SCIP_CALL( SCIPincConsAge(scip, cons) );
7401  }
7402  }
7403 
7404  /* update absolute and relative violation of the solution */
7405  if( sol != NULL )
7406  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7407 
7408  return SCIP_OKAY;
7409 }
7410 
7411 /** creates an LP row in a linear constraint data */
7412 static
7414  SCIP* scip, /**< SCIP data structure */
7415  SCIP_CONS* cons /**< linear constraint */
7416  )
7417 {
7418  SCIP_CONSDATA* consdata;
7419 
7420  assert(scip != NULL);
7421  assert(cons != NULL);
7422 
7423  consdata = SCIPconsGetData(cons);
7424  assert(consdata != NULL);
7425  assert(consdata->row == NULL);
7426 
7427  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7429 
7430  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7431 
7432  return SCIP_OKAY;
7433 }
7434 
7435 /** adds linear constraint as cut to the LP */
7436 static
7438  SCIP* scip, /**< SCIP data structure */
7439  SCIP_CONS* cons, /**< linear constraint */
7440  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7441  )
7442 {
7443  SCIP_CONSDATA* consdata;
7444 
7445  assert(scip != NULL);
7446  assert(cons != NULL);
7447 
7448  consdata = SCIPconsGetData(cons);
7449  assert(consdata != NULL);
7450 
7451  if( consdata->row == NULL )
7452  {
7453  /* convert consdata object into LP row */
7454  SCIP_CALL( createRow(scip, cons) );
7455  }
7456  assert(consdata->row != NULL);
7457 
7458  if( consdata->nvars == 0 )
7459  {
7460  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7461  }
7462 
7463  /* insert LP row as cut */
7464  if( !SCIProwIsInLP(consdata->row) )
7465  {
7466  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7467  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7468  /* if presolving is turned off, the row might be trivial */
7469  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7470  {
7471  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7472  }
7473 #ifndef NDEBUG
7474  else
7475  {
7476  int pr;
7477  int cr;
7478  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7479  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7480  assert( pr == 0 || cr == 0 );
7481  }
7482 #endif
7483  }
7484 
7485  return SCIP_OKAY;
7486 }
7487 
7488 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7489 static
7491  SCIP* scip, /**< SCIP data structure */
7492  SCIP_CONS* cons, /**< linear constraint */
7493  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7494  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7495  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7496  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7497  * the ones with non-zero dual value? */
7498  int* ncuts, /**< pointer to add up the number of found cuts */
7499  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7500  )
7501 {
7502  SCIP_CONSDATA* consdata;
7503  SCIP_Bool violated;
7504  int oldncuts;
7505 
7506  assert(scip != NULL);
7507  assert(conshdlrdata != NULL);
7508  assert(cons != NULL);
7509  assert(cutoff != NULL);
7510 
7511  consdata = SCIPconsGetData(cons);
7512  assert(ncuts != NULL);
7513  assert(consdata != NULL);
7514 
7515  oldncuts = *ncuts;
7516  *cutoff = FALSE;
7517 
7518  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7519 
7520  if( violated )
7521  {
7522  /* insert LP row as cut */
7523  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7524  (*ncuts)++;
7525  }
7526  else if( !SCIPconsIsModifiable(cons) && separatecards )
7527  {
7528  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7529  if( !separateall && sol == NULL )
7530  {
7531  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7532  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7533  {
7534  SCIP_Real dualsol;
7535 
7536  dualsol = SCIProwGetDualsol(consdata->row);
7537  if( SCIPisFeasNegative(scip, dualsol) )
7538  {
7539  if( !SCIPisInfinity(scip, consdata->rhs) )
7540  {
7541  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7542  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7543  }
7544  }
7545  else if( SCIPisFeasPositive(scip, dualsol) )
7546  {
7547  if( !SCIPisInfinity(scip, -consdata->lhs) )
7548  {
7549  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7550  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7551  }
7552  }
7553  }
7554  }
7555  else
7556  {
7557  if( !SCIPisInfinity(scip, consdata->rhs) )
7558  {
7559  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7560  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7561  }
7562  if( !SCIPisInfinity(scip, -consdata->lhs) )
7563  {
7564  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7565  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7566  }
7567  }
7568  }
7569 
7570  if( *ncuts > oldncuts )
7571  {
7572  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7573  }
7574 
7575  return SCIP_OKAY;
7576 }
7577 
7578 /** propagation method for linear constraints */
7579 static
7581  SCIP* scip, /**< SCIP data structure */
7582  SCIP_CONS* cons, /**< linear constraint */
7583  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7584  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7585  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7586  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7587  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7588  int* nchgbds /**< pointer to count the total number of tightened bounds */
7589  )
7590 {
7591  SCIP_CONSDATA* consdata;
7592  SCIP_Real minactivity;
7593  SCIP_Real maxactivity;
7594  SCIP_Bool minactisrelax;
7595  SCIP_Bool maxactisrelax;
7596 
7597  assert(scip != NULL);
7598  assert(cons != NULL);
7599  assert(cutoff != NULL);
7600  assert(nchgbds != NULL);
7601 
7602  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7603 
7604  consdata = SCIPconsGetData(cons);
7605  assert(consdata != NULL);
7606 
7607  if( consdata->eventdata == NULL )
7608  {
7609  SCIP_CONSHDLR* conshdlr;
7610  SCIP_CONSHDLRDATA* conshdlrdata;
7611 
7612  conshdlr = SCIPconsGetHdlr(cons);
7613  assert(conshdlr != NULL);
7614 
7615  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7616  assert(conshdlrdata != NULL);
7617 
7618  /* catch bound change events of variables */
7619  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7620  assert(consdata->eventdata != NULL);
7621  }
7622 
7623  *cutoff = FALSE;
7624 
7625  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7626  if( !SCIPconsIsModifiable(cons) )
7627  {
7628  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7629  if( !SCIPinRepropagation(scip) )
7630  {
7631  SCIP_CALL( SCIPincConsAge(scip, cons) );
7632  }
7633 
7634  /* tighten the variable's bounds */
7635  if( tightenbounds )
7636  {
7637  int oldnchgbds;
7638 
7639  oldnchgbds = *nchgbds;
7640 
7641  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7642 
7643  if( *nchgbds > oldnchgbds )
7644  {
7645  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7646  }
7647  }
7648 
7649  /* propagate ranged rows */
7650  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7651  {
7652  int nfixedvars;
7653  int naddconss;
7654  /* cppcheck-suppress unassignedVariable */
7655  int oldnchgbds;
7656 
7657  nfixedvars = 0;
7658  naddconss = 0;
7659  SCIPdebug( oldnchgbds = *nchgbds; )
7660 
7661  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7662 
7663  if( *cutoff )
7664  {
7665  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7666  }
7667  else
7668  {
7669  SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars);
7670  }
7671 
7672  if( nfixedvars > 0 )
7673  *nchgbds += 2*nfixedvars;
7674  }
7675 
7676  /* check constraint for infeasibility and redundancy */
7677  if( !(*cutoff) )
7678  {
7679  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7680 
7681  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7682  {
7683  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7684  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7685 
7686  /* analyze conflict */
7687  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7688 
7689  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7690  *cutoff = TRUE;
7691  }
7692  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7693  {
7694  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7695  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7696 
7697  /* analyze conflict */
7698  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7699 
7700  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7701  *cutoff = TRUE;
7702  }
7703  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7704  {
7705  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7706  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7707 
7708  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7709  if( consdata->nvars > 0 )
7710  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7711  else
7712  SCIP_CALL( SCIPdelCons(scip, cons) );
7713  }
7714  }
7715  }
7716 
7717  return SCIP_OKAY;
7718 }
7719 
7720 
7721 /*
7722  * Presolving methods
7723  */
7724 
7725 /** converts all variables with fixed domain into FIXED variables */
7726 static
7728  SCIP* scip, /**< SCIP data structure */
7729  SCIP_CONS* cons, /**< linear constraint */
7730  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7731  int* nfixedvars /**< pointer to count the total number of fixed variables */
7732  )
7733 {
7734  SCIP_CONSDATA* consdata;
7735  SCIP_VAR* var;
7736  SCIP_VARSTATUS varstatus;
7737  SCIP_Real lb;
7738  SCIP_Real ub;
7739  SCIP_Bool fixed;
7740  SCIP_Bool infeasible;
7741  int v;
7742 
7743  assert(scip != NULL);
7744  assert(cons != NULL);
7745  assert(cutoff != NULL);
7746  assert(nfixedvars != NULL);
7747 
7748  consdata = SCIPconsGetData(cons);
7749  assert(consdata != NULL);
7750 
7751  for( v = 0; v < consdata->nvars; ++v )
7752  {
7753  assert(consdata->vars != NULL);
7754  var = consdata->vars[v];
7755  varstatus = SCIPvarGetStatus(var);
7756 
7757  if( varstatus != SCIP_VARSTATUS_FIXED )
7758  {
7759  lb = SCIPvarGetLbGlobal(var);
7760  ub = SCIPvarGetUbGlobal(var);
7761  if( SCIPisEQ(scip, lb, ub) )
7762  {
7763  SCIP_Real fixval;
7764 
7765  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7766  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7767  SCIPvarGetName(var), lb, ub, fixval);
7768  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7769  if( infeasible )
7770  {
7771  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7772  *cutoff = TRUE;
7773  return SCIP_OKAY;
7774  }
7775  if( fixed )
7776  (*nfixedvars)++;
7777  }
7778  }
7779  }
7780 
7781  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7782 
7783  if( infeasible )
7784  {
7785  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7786  *cutoff = TRUE;
7787  return SCIP_OKAY;
7788  }
7789 
7790  assert(consdata->removedfixings);
7791 
7792  return SCIP_OKAY;
7793 }
7794 
7795 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7796 
7797 /** extracts cliques of the constraint and adds them to SCIP
7798  *
7799  * The following clique extraction mechanism are implemeneted
7800  *
7801  * 1. collect binary variables and sort them in non increasing order, then
7802  *
7803  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7804  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7805  * condition
7806  *
7807  * minactivity + vals[i] + vals[i+1] > rhs
7808  *
7809  * and also add the binary to binary implication also for non-successive variables for which the same argument
7810  * holds
7811  *
7812  * minactivity + vals[i] + vals[j] > rhs
7813  *
7814  * 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
7815  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7816  *
7817  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7818  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7819  * condition
7820  *
7821  * maxactivity + vals[i] + vals[i-1] < lhs
7822  *
7823  * and also add the binary to binary implication also for non-successive variables for which the same argument
7824  * holds
7825  *
7826  * maxactivity + vals[i] + vals[j] < lhs
7827  *
7828  * e.g. you could multiply the above example by -1
7829  *
7830  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7831  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7832  * condition
7833  *
7834  * minactivity - vals[i] - vals[i-1] > rhs
7835  *
7836  * and also add the binary to binary implication also for non-successive variables for which the
7837  * same argument holds
7838  *
7839  * minactivity - vals[i] - vals[j] > rhs
7840  *
7841  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7842  * implication x1 = 0 => x3 = 1
7843  *
7844  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7845  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7846  * condition
7847  *
7848  * maxactivity - vals[i] - vals[i+1] < lhs
7849  *
7850  * and also add the binary to binary implication also for non-successive variables for which the same argument
7851  * holds
7852  *
7853  * maxactivity - vals[i] - vals[j] < lhs
7854  *
7855  * e.g. you could multiply the above example by -1
7856  *
7857  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7858  * as clique, (this part is done at the end of the method)
7859  *
7860  */
7861 static
7863  SCIP* scip, /**< SCIP data structure */
7864  SCIP_CONS* cons, /**< linear constraint */
7865  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7866  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7867  int* nfixedvars, /**< pointer to count number of fixed variables */
7868  int* nchgbds, /**< pointer to count the total number of tightened bounds */
7869  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7870  )
7871 {
7872  SCIP_VAR** vars;
7873  SCIP_Real* vals;
7874  SCIP_CONSDATA* consdata;
7875  SCIP_Bool lhsclique;
7876  SCIP_Bool rhsclique;
7877  SCIP_Bool finitelhs;
7878  SCIP_Bool finiterhs;
7879  SCIP_Bool finiteminact;
7880  SCIP_Bool finitemaxact;
7881  SCIP_Bool finitenegminact;
7882  SCIP_Bool finitenegmaxact;
7883  SCIP_Bool finiteposminact;
7884  SCIP_Bool finiteposmaxact;
7885  SCIP_Bool infeasible;
7886  SCIP_Bool stopped;
7887  int cliquenonzerosadded;
7888  int v;
7889  int i;
7890  int nposcoefs;
7891  int nnegcoefs;
7892  int nvars;
7893 
7894  assert(scip != NULL);
7895  assert(cons != NULL);
7896  assert(nfixedvars != NULL);
7897  assert(nchgbds != NULL);
7898  assert(cutoff != NULL);
7899  assert(!SCIPconsIsDeleted(cons));
7900 
7901  consdata = SCIPconsGetData(cons);
7902  assert(consdata != NULL);
7903 
7904  if( consdata->nvars < 2 )
7905  return SCIP_OKAY;
7906 
7907  /* add implications if posibble
7908  *
7909  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7910  * maximal absolute contribution and also only if this variable would force all other variables to their bound
7911  * corresponding to the global minimal activity of the constraint
7912  */
7913  if( !consdata->implsadded )
7914  {
7915  /* sort variables by variable type */
7916  SCIP_CALL( consdataSort(scip, consdata) );
7917 
7918  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7919  * up front, might change sorting correspondingly
7920  */
7921  /* fast abort if no binaries exist */
7922  if( !SCIPvarIsBinary(consdata->vars[0]) )
7923  return SCIP_OKAY;
7924 
7925  nvars = consdata->nvars;
7926  vars = consdata->vars;
7927  vals = consdata->vals;
7928 
7929  /* recompute activities if needed */
7930  if( !consdata->validactivities )
7931  consdataCalcActivities(scip, consdata);
7932  assert(consdata->validactivities);
7933 
7934  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7935  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7936  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7937  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7938  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7939  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7940  finiteminact = (finitenegminact && finiteposminact);
7941  finitemaxact = (finitenegmaxact && finiteposmaxact);
7942 
7943  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7944  {
7945  SCIP_Real maxabscontrib = -1.0;
7946  SCIP_Bool posval = FALSE;
7947  SCIP_Bool allbinary = TRUE;
7948  int oldnchgbds = *nchgbds;
7949  int nbdchgs = 0;
7950  int nimpls = 0;
7951  int position = -1;
7952 
7953  /* we need a valid minimal/maximal activity to add cliques */
7954  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
7955  {
7956  consdataRecomputeGlbMinactivity(scip, consdata);
7957  assert(consdata->validglbminact);
7958  }
7959 
7960  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
7961  {
7962  consdataRecomputeGlbMaxactivity(scip, consdata);
7963  assert(consdata->validglbmaxact);
7964  }
7965  assert(consdata->validglbminact || consdata->validglbmaxact);
7966 
7967  /* @todo extend this to local/constraint probing */
7968 
7969  /* determine maximal contribution to the activity */
7970  for( v = nvars - 1; v >= 0; --v )
7971  {
7972  if( SCIPvarIsBinary(vars[v]) )
7973  {
7974  if( vals[v] > 0 )
7975  {
7976  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
7977 
7978  if( value > maxabscontrib )
7979  {
7980  maxabscontrib = value;
7981  position = v;
7982  posval = TRUE;
7983  }
7984  }
7985  else
7986  {
7987  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
7988 
7989  value = REALABS(value);
7990 
7991  if( value > maxabscontrib )
7992  {
7993  maxabscontrib = value;
7994  position = v;
7995  posval = FALSE;
7996  }
7997  }
7998  }
7999  else
8000  allbinary = FALSE;
8001  }
8002  assert(0 <= position && position < nvars);
8003 
8004  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8005  {
8006  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8007  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8008  * implications
8009  */
8010  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
8011  {
8012  for( v = nvars - 1; v >= 0; --v )
8013  {
8014  /* binary to binary implications will be collected when extrating cliques */
8015  if( !SCIPvarIsBinary(vars[v]) )
8016  {
8017  if( v != position )
8018  {
8019  if( vals[v] > 0 )
8020  {
8021  /* add implications */
8022  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8023  ++nimpls;
8024  *nchgbds += nbdchgs;
8025  }
8026  else
8027  {
8028  /* add implications */
8029  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8030  ++nimpls;
8031  *nchgbds += nbdchgs;
8032  }
8033 
8034  if( infeasible )
8035  {
8036  *cutoff = TRUE;
8037  break;
8038  }
8039  }
8040  }
8041  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8042  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8043  break;
8044  }
8045  }
8046 
8047  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8048  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8049  * implications
8050  */
8051  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
8052  {
8053  for( v = nvars - 1; v >= 0; --v )
8054  {
8055  /* binary to binary implications will be collected when extrating cliques */
8056  if( !SCIPvarIsBinary(vars[v]) )
8057  {
8058  if( v != position )
8059  {
8060  if( vals[v] > 0 )
8061  {
8062  /* add implications */
8063  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8064  ++nimpls;
8065  *nchgbds += nbdchgs;
8066  }
8067  else
8068  {
8069  /* add implications */
8070  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8071  ++nimpls;
8072  *nchgbds += nbdchgs;
8073  }
8074 
8075  if( infeasible )
8076  {
8077  *cutoff = TRUE;
8078  break;
8079  }
8080  }
8081  }
8082  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8083  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8084  break;
8085  }
8086  }
8087 
8088  /* did we find some implications */
8089  if( nimpls > 0 )
8090  {
8091  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8092 
8093  if( *cutoff )
8094  return SCIP_OKAY;
8095 
8096  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8097  if( *nchgbds - oldnchgbds > 0 )
8098  {
8099  /* check for fixed variables */
8100  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8101  if( *cutoff )
8102  return SCIP_OKAY;
8103 
8104  /* tighten variable's bounds */
8105  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8106  if( *cutoff )
8107  return SCIP_OKAY;
8108 
8109  /* check for fixed variables */
8110  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8111  if( *cutoff )
8112  return SCIP_OKAY;
8113  }
8114  }
8115  }
8116  }
8117 
8118  consdata->implsadded = TRUE;
8119  }
8120 
8121  /* check if we already added the cliques of this constraint */
8122  if( consdata->cliquesadded )
8123  return SCIP_OKAY;
8124 
8125  consdata->cliquesadded = TRUE;
8126  cliquenonzerosadded = 0;
8127  stopped = FALSE;
8128 
8129  /* sort variables by variable type */
8130  SCIP_CALL( consdataSort(scip, consdata) );
8131 
8132  nvars = consdata->nvars;
8133  vars = consdata->vars;
8134  vals = consdata->vals;
8135 
8136  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8137 
8138  /* recompute activities if needed */
8139  if( !consdata->validactivities )
8140  consdataCalcActivities(scip, consdata);
8141  assert(consdata->validactivities);
8142 
8143  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8144  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8145  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8146  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8147  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8148  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8149  finiteminact = (finitenegminact && finiteposminact);
8150  finitemaxact = (finitenegmaxact && finiteposmaxact);
8151 
8152  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8153  * information
8154  */
8155  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8156  {
8157  SCIP_VAR** binvars;
8158  SCIP_Real* binvarvals;
8159  int nposbinvars = 0;
8160  int nnegbinvars = 0;
8161  int allonebinary = 0;
8162 
8163  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8164  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8165 
8166  /* collect binary variables */
8167  for( i = 0; i < nvars; ++i )
8168  {
8169  if( SCIPvarIsBinary(vars[i]) )
8170  {
8171  assert(!SCIPisZero(scip, vals[i]));
8172 
8173  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8174  ++allonebinary;
8175 
8176  binvars[nposbinvars + nnegbinvars] = vars[i];
8177  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8178 
8179  if( SCIPisPositive(scip, vals[i]) )
8180  ++nposbinvars;
8181  else
8182  ++nnegbinvars;
8183 
8184  assert(nposbinvars + nnegbinvars <= nvars);
8185  }
8186  /* stop searching for binary variables, because the constraint data is sorted */
8187  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8188  break;
8189  }
8190  assert(nposbinvars + nnegbinvars <= nvars);
8191 
8192  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8193  * cliques
8194  */
8195  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8196  {
8197  SCIP_Real threshold;
8198  int oldnchgbds = *nchgbds;
8199  int nbdchgs;
8200  int jstart;
8201  int j;
8202 
8203  /* we need a valid minimal/maximal activity to add cliques */
8204  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8205  {
8206  consdataRecomputeGlbMinactivity(scip, consdata);
8207  assert(consdata->validglbminact);
8208  }
8209 
8210  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8211  {
8212  consdataRecomputeGlbMaxactivity(scip, consdata);
8213  assert(consdata->validglbmaxact);
8214  }
8215  assert(consdata->validglbminact || consdata->validglbmaxact);
8216 
8217  /* sort coefficients non-increasing to be faster in the clique search */
8218  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8219 
8220  /* case a) */
8221  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8222  {
8223  /* compute value that needs to be exceeded */
8224  threshold = consdata->rhs - consdata->glbminactivity;
8225 
8226  i = 0;
8227  j = i + 1;
8228 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8229  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8230  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
8231 #endif
8232  /* check if at least two variables are in a clique */
8233  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
8234  {
8235  ++j;
8236  /* check for extending the clique */
8237  while( j < nposbinvars )
8238  {
8239  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8240  break;
8241  ++j;
8242  }
8243  assert(j >= 2);
8244 
8245  /* add clique with at least two variables */
8246  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, FALSE, &infeasible, &nbdchgs) );
8247 
8248  if( infeasible )
8249  *cutoff = TRUE;
8250 
8251  *nchgbds += nbdchgs;
8252 
8253  cliquenonzerosadded += j;
8254  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8255  stopped = TRUE;
8256 
8257  /* exchange the last variable in the clique if possible and add all new ones */
8258  if( !stopped && !(*cutoff) && j < nposbinvars )
8259  {
8260  SCIP_VAR** clqvars;
8261  int lastfit = j - 2;
8262  assert(lastfit >= i);
8263 
8264  /* copy all 'main'-clique variables */
8265  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8266 
8267  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8268  while( lastfit >= i && j < nposbinvars )
8269  {
8270  /* check if two variables are in a clique */
8271  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8272  {
8273  clqvars[lastfit + 1] = binvars[j];
8274 
8275  /* add clique with at least two variables */
8276  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8277 
8278  if( infeasible )
8279  {
8280  *cutoff = TRUE;
8281  break;
8282  }
8283 
8284  *nchgbds += nbdchgs;
8285 
8286  cliquenonzerosadded += (lastfit - i + 2);
8287  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8288  {
8289  stopped = TRUE;
8290  break;
8291  }
8292 
8293  ++j;
8294  }
8295  else
8296  --lastfit;
8297  }
8298 
8299  SCIPfreeBufferArray(scip, &clqvars);
8300  }
8301  }
8302  }
8303 
8304  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8305  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8306  {
8307  /* check for fixed variables */
8308  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8309 
8310  if( !*cutoff )
8311  {
8312  /* tighten variable's bounds */
8313  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8314 
8315  if( !*cutoff )
8316  {
8317  /* check for fixed variables */
8318  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8319 
8320  if( !*cutoff )
8321  {
8322  /* sort variables by variable type */
8323  SCIP_CALL( consdataSort(scip, consdata) );
8324 
8325  /* recompute activities if needed */
8326  if( !consdata->validactivities )
8327  consdataCalcActivities(scip, consdata);
8328  assert(consdata->validactivities);
8329 
8330  nvars = consdata->nvars;
8331  vars = consdata->vars;
8332  vals = consdata->vals;
8333  nposbinvars = 0;
8334  nnegbinvars = 0;
8335  allonebinary = 0;
8336 
8337  /* update binary variables */
8338  for( i = 0; i < nvars; ++i )
8339  {
8340  if( SCIPvarIsBinary(vars[i]) )
8341  {
8342  assert(!SCIPisZero(scip, vals[i]));
8343 
8344  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8345  ++allonebinary;
8346 
8347  binvars[nposbinvars + nnegbinvars] = vars[i];
8348  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8349 
8350  if( SCIPisPositive(scip, vals[i]) )
8351  ++nposbinvars;
8352  else
8353  ++nnegbinvars;
8354 
8355  assert(nposbinvars + nnegbinvars <= nvars);
8356  }
8357  /* stop searching for binary variables, because the constraint data is sorted */
8358  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8359  break;
8360  }
8361  assert(nposbinvars + nnegbinvars <= nvars);
8362  }
8363  }
8364  }
8365 
8366  oldnchgbds = *nchgbds;
8367  }
8368 
8369  /* case b) */
8370  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8371  {
8372  /* compute value that needs to be deceeded */
8373  threshold = consdata->lhs - consdata->glbmaxactivity;
8374 
8375  i = nposbinvars + nnegbinvars - 1;
8376  j = i - 1;
8377 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8378  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8379  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8380 #endif
8381  /* check if two variables are in a clique */
8382  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8383  {
8384  --j;
8385  /* check for extending the clique */
8386  while( j >= nposbinvars )
8387  {
8388  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8389  break;
8390  --j;
8391  }
8392  jstart = j;
8393 
8394  assert(i - j >= 2);
8395  /* add clique with at least two variables */
8396  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8397 
8398  if( infeasible )
8399  *cutoff = TRUE;
8400 
8401  *nchgbds += nbdchgs;
8402 
8403  cliquenonzerosadded += (i - j);
8404  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8405  stopped = TRUE;
8406 
8407  /* exchange the last variable in the clique if possible and add all new ones */
8408  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8409  {
8410  SCIP_VAR** clqvars;
8411  int lastfit = jstart + 1;
8412  assert(lastfit < i);
8413 
8414  /* copy all 'main'-clique variables */
8415  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8416  ++lastfit;
8417 
8418  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8419  while( lastfit <= i && j >= nposbinvars )
8420  {
8421  /* check if two variables are in a clique */
8422  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8423  {
8424  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8425  clqvars[lastfit - jstart - 2] = binvars[j];
8426 
8427  assert(i - lastfit + 2 >= 2);
8428  /* add clique with at least two variables */
8429  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8430 
8431  if( infeasible )
8432  {
8433  *cutoff = TRUE;
8434  break;
8435  }
8436 
8437  *nchgbds += nbdchgs;
8438 
8439  cliquenonzerosadded += (i - 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 c) */
8523  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8524  {
8525  SCIP_Bool* values;
8526 
8527  /* initialize clique values array for adding a negated clique */
8528  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8529  BMSclearMemoryArray(values, nnegbinvars);
8530 
8531  /* compute value that needs to be exceeded */
8532  threshold = consdata->rhs - consdata->glbminactivity;
8533 
8534  i = nposbinvars + nnegbinvars - 1;
8535  j = i - 1;
8536 
8537 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8538  /* check if the variable should not have already been fixed to one */
8539  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8540 #endif
8541 
8542  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8543  {
8544  --j;
8545  /* check for extending the clique */
8546  while( j >= nposbinvars )
8547  {
8548  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8549  break;
8550  --j;
8551  }
8552  jstart = j;
8553 
8554  assert(i - j >= 2);
8555  /* add negated clique with at least two variables */
8556  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8557 
8558  if( infeasible )
8559  *cutoff = TRUE;
8560 
8561  *nchgbds += nbdchgs;
8562 
8563  cliquenonzerosadded += (i - j);
8564  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8565  stopped = TRUE;
8566 
8567  /* exchange the last variable in the clique if possible and add all new ones */
8568  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8569  {
8570  SCIP_VAR** clqvars;
8571  int lastfit = j + 1;
8572  assert(lastfit < i);
8573 
8574  /* copy all 'main'-clique variables */
8575  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8576  ++lastfit;
8577 
8578  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8579  while( lastfit <= i && j >= nposbinvars )
8580  {
8581  /* check if two variables are in a negated clique */
8582  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8583  {
8584  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8585  clqvars[lastfit - jstart - 2] = binvars[j];
8586 
8587  assert(i - lastfit + 2 >= 2);
8588  /* add clique with at least two variables */
8589  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8590 
8591  if( infeasible )
8592  {
8593  *cutoff = TRUE;
8594  break;
8595  }
8596 
8597  *nchgbds += nbdchgs;
8598 
8599  cliquenonzerosadded += (i - lastfit + 2);
8600  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8601  {
8602  stopped = TRUE;
8603  break;
8604  }
8605 
8606  --j;
8607  }
8608  else
8609  ++lastfit;
8610  }
8611 
8612  SCIPfreeBufferArray(scip, &clqvars);
8613  }
8614  }
8615 
8616  SCIPfreeBufferArray(scip, &values);
8617  }
8618 
8619  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8620  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8621  {
8622  /* check for fixed variables */
8623  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8624 
8625  if( !*cutoff )
8626  {
8627  /* tighten variable's bounds */
8628  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8629 
8630  if( !*cutoff )
8631  {
8632  /* check for fixed variables */
8633  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8634 
8635  if( !*cutoff )
8636  {
8637  /* sort variables by variable type */
8638  SCIP_CALL( consdataSort(scip, consdata) );
8639 
8640  /* recompute activities if needed */
8641  if( !consdata->validactivities )
8642  consdataCalcActivities(scip, consdata);
8643  assert(consdata->validactivities);
8644 
8645  nvars = consdata->nvars;
8646  vars = consdata->vars;
8647  vals = consdata->vals;
8648  nposbinvars = 0;
8649  nnegbinvars = 0;
8650  allonebinary = 0;
8651 
8652  /* update binary variables */
8653  for( i = 0; i < nvars; ++i )
8654  {
8655  if( SCIPvarIsBinary(vars[i]) )
8656  {
8657  assert(!SCIPisZero(scip, vals[i]));
8658 
8659  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8660  ++allonebinary;
8661 
8662  binvars[nposbinvars + nnegbinvars] = vars[i];
8663  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8664 
8665  if( SCIPisPositive(scip, vals[i]) )
8666  ++nposbinvars;
8667  else
8668  ++nnegbinvars;
8669 
8670  assert(nposbinvars + nnegbinvars <= nvars);
8671  }
8672  /* stop searching for binary variables, because the constraint data is sorted */
8673  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8674  break;
8675  }
8676  assert(nposbinvars + nnegbinvars <= nvars);
8677  }
8678  }
8679  }
8680  }
8681 
8682  /* case d) */
8683  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8684  {
8685  SCIP_Bool* values;
8686 
8687  /* initialize clique values array for adding a negated clique */
8688  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8689  BMSclearMemoryArray(values, nposbinvars);
8690 
8691  /* compute value that needs to be exceeded */
8692  threshold = consdata->lhs - consdata->glbmaxactivity;
8693 
8694  i = 0;
8695  j = i + 1;
8696 
8697 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8698  /* check if the variable should not have already been fixed to one */
8699  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
8700 #endif
8701 
8702  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8703  {
8704  ++j;
8705  /* check for extending the clique */
8706  while( j < nposbinvars )
8707  {
8708  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8709  break;
8710  ++j;
8711  }
8712  assert(j >= 2);
8713 
8714  /* add negated clique with at least two variables */
8715  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, FALSE, &infeasible, &nbdchgs) );
8716 
8717  if( infeasible )
8718  *cutoff = TRUE;
8719 
8720  *nchgbds += nbdchgs;
8721 
8722  cliquenonzerosadded += j;
8723  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8724  stopped = TRUE;
8725 
8726  /* exchange the last variable in the clique if possible and add all new ones */
8727  if( !stopped && !(*cutoff) && j < nposbinvars )
8728  {
8729  SCIP_VAR** clqvars;
8730  int lastfit = j - 2;
8731  assert(lastfit >= i);
8732 
8733  /* copy all 'main'-clique variables */
8734  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8735 
8736  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8737  while( lastfit >= i && j < nposbinvars )
8738  {
8739  /* check if two variables are in a negated clique */
8740  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8741  {
8742  clqvars[lastfit + 1] = binvars[j];
8743 
8744  /* add clique with at least two variables */
8745  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8746 
8747  if( infeasible )
8748  {
8749  *cutoff = TRUE;
8750  break;
8751  }
8752 
8753  *nchgbds += nbdchgs;
8754 
8755  cliquenonzerosadded += (lastfit - i + 2);
8756  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8757  break;
8758 
8759  ++j;
8760  }
8761  else
8762  --lastfit;
8763  }
8764 
8765  SCIPfreeBufferArray(scip, &clqvars);
8766  }
8767  }
8768 
8769  SCIPfreeBufferArray(scip, &values);
8770  }
8771  }
8772 
8773  SCIPfreeBufferArray(scip, &binvarvals);
8774  SCIPfreeBufferArray(scip, &binvars);
8775 
8776  if( *cutoff )
8777  return SCIP_OKAY;
8778  }
8779 
8780  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8781 
8782  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8783  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8784  */
8785  nposcoefs = 0;
8786  nnegcoefs = 0;
8787  for( i = 0; i < nvars; ++i )
8788  {
8789  if( !SCIPvarIsBinary(vars[i]) )
8790  return SCIP_OKAY;
8791  else if( SCIPisEQ(scip, vals[i], +1.0) )
8792  nposcoefs++;
8793  else if( SCIPisEQ(scip, vals[i], -1.0) )
8794  nnegcoefs++;
8795  else
8796  return SCIP_OKAY;
8797  }
8798 
8799  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8800  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8801 
8802  if( lhsclique || rhsclique )
8803  {
8804  SCIP_Bool* values;
8805  int nbdchgs;
8806 
8807  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8808  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8809  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8810 
8811  for( i = 0; i < nvars; ++i )
8812  values[i] = (rhsclique == (vals[i] > 0.0));
8813 
8814  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8815 
8816  if( infeasible )
8817  *cutoff = TRUE;
8818 
8819  *nchgbds += nbdchgs;
8820  SCIPfreeBufferArray(scip, &values);
8821  }
8822 
8823  return SCIP_OKAY;
8824 }
8825 
8826 /** tightens left and right hand side of constraint due to integrality */
8827 static
8829  SCIP* scip, /**< SCIP data structure */
8830  SCIP_CONS* cons, /**< linear constraint */
8831  int* nchgsides, /**< pointer to count number of side changes */
8832  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8833  )
8834 {
8835  SCIP_CONSDATA* consdata;
8836  SCIP_Real newlhs;
8837  SCIP_Real newrhs;
8838  SCIP_Bool chglhs;
8839  SCIP_Bool chgrhs;
8840  SCIP_Bool integral;
8841  int i;
8842 
8843  assert(scip != NULL);
8844  assert(cons != NULL);
8845  assert(nchgsides != NULL);
8846 
8847  consdata = SCIPconsGetData(cons);
8848  assert(consdata != NULL);
8849 
8850  *infeasible = FALSE;
8851 
8852  chglhs = FALSE;
8853  chgrhs = FALSE;
8854  newlhs = -SCIPinfinity(scip);
8855  newrhs = SCIPinfinity(scip);
8856 
8857  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8858  {
8859  integral = TRUE;
8860  for( i = 0; i < consdata->nvars && integral; ++i )
8861  {
8862  integral = SCIPisIntegral(scip, consdata->vals[i])
8863  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8864  }
8865  if( integral )
8866  {
8867  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8868  {
8869  newlhs = SCIPfeasCeil(scip, consdata->lhs);
8870  chglhs = TRUE;
8871  }
8872  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8873  {
8874  newrhs = SCIPfeasFloor(scip, consdata->rhs);
8875  chgrhs = TRUE;
8876  }
8877 
8878  /* check whether rounding would lead to an unsatisfiable constraint */
8879  if( SCIPisGT(scip, newlhs, newrhs) )
8880  {
8881  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8882  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8883 
8884  *infeasible = TRUE;
8885  return SCIP_OKAY;
8886  }
8887 
8888  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8889  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8890 
8891  if( chglhs )
8892  {
8893  assert(!SCIPisInfinity(scip, -newlhs));
8894 
8895  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8896  if( !consdata->upgraded )
8897  (*nchgsides)++;
8898  }
8899  if( chgrhs )
8900  {
8901  assert(!SCIPisInfinity(scip, newrhs));
8902 
8903  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8904  if( !consdata->upgraded )
8905  (*nchgsides)++;
8906  }
8907  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8908  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8909  }
8910  }
8911 
8912  return SCIP_OKAY;
8913 }
8914 
8915 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8916  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8917  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8918  * (i) ai >= 0:
8919  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8920  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8921  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8922  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8923  * - change coefficients:
8924  * ai' := max(lhs - minact, maxact - rhs)
8925  * lhs' := lhs - (ai - ai')*li
8926  * rhs' := rhs - (ai - ai')*ui
8927  * (ii) ai < 0:
8928  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8929  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8930  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8931  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8932  * - change coefficients:
8933  * ai' := min(rhs - maxact, minact - lhs)
8934  * lhs' := lhs - (ai - ai')*ui
8935  * rhs' := rhs - (ai - ai')*li
8936  *
8937  * We further try to remove redundant variable from the constraint;
8938  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
8939  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8940  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
8941  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
8942  * 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
8943  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
8944  *
8945  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8946  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8947  */
8948 static
8950  SCIP* scip, /**< SCIP data structure */
8951  SCIP_CONS* cons, /**< linear constraint */
8952  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8953  int* nchgsides /**< pointer to count number of side changes */
8954  )
8955 {
8956  SCIP_CONSDATA* consdata;
8957  SCIP_VAR* var;
8958  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
8959  * activity, ignoring the coefficients contributing with infinite value */
8960  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
8961  * activity, ignoring the coefficients contributing with infinite value */
8962  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
8963  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
8964  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
8965  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
8966  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
8967  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
8968  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
8969  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
8970  SCIP_Real val;
8971  SCIP_Real newval;
8972  SCIP_Real newlhs;
8973  SCIP_Real newrhs;
8974  SCIP_Real lb;
8975  SCIP_Real ub;
8976  int i;
8977 
8978  assert(scip != NULL);
8979  assert(cons != NULL);
8980  assert(nchgcoefs != NULL);
8981  assert(nchgsides != NULL);
8982 
8983  consdata = SCIPconsGetData(cons);
8984  assert(consdata != NULL);
8985 
8986  /* @todo Is this still needed with automatic recomputation of activities? */
8987  /* if the maximal coefficient is too large, recompute the activities */
8988  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
8989  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
8990  {
8991  consdataRecomputeMinactivity(scip, consdata);
8992  consdataRecomputeMaxactivity(scip, consdata);
8993  }
8994 
8995  /* get the minimal and maximal activity of the constraint */
8996  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8997 
8998  minleftactivity = 0.0;
8999  maxleftactivity = 0.0;
9000 
9001  /* try to tighten each coefficient */
9002  i = 0;
9003  while( i < consdata->nvars )
9004  {
9005  var = consdata->vars[i];
9006 
9007  /* get coefficient and variable's bounds */
9008  lb = SCIPvarGetLbLocal(var);
9009  ub = SCIPvarGetUbLocal(var);
9010  val = consdata->vals[i];
9011  assert(!SCIPisZero(scip, val));
9012 
9013  /* check sign of coefficient */
9014  if( val >= 0.0 )
9015  {
9016  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9018  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9019  {
9020  /* change coefficients:
9021  * ai' := max(lhs - minact, maxact - rhs)
9022  * lhs' := lhs - (ai - ai')*li
9023  * rhs' := rhs - (ai - ai')*ui
9024  */
9025 
9026  lval = consdata->lhs - minactivity;
9027  rval = maxactivity - consdata->rhs;
9028 
9029  /* Try to avoid cancellation, if there are only two variables */
9030  if( consdata->nvars == 2 )
9031  {
9032  SCIP_Real otherval;
9033  otherval = consdata->vals[1-i];
9034 
9035  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9036  {
9037  lval = consdata->lhs - val*lb;
9038  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9039  }
9040 
9041  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9042  {
9043  rval = val*ub - consdata->rhs;
9044  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9045  }
9046  }
9047 
9048  newval = MAX(lval, rval);
9049  assert(SCIPisSumRelLE(scip, newval, val));
9050 
9051  /* Try to avoid cancellation in computation of lhs/rhs */
9052  newlhs = consdata->lhs - val * lb;
9053  newlhs += newval * lb;
9054  newrhs = consdata->rhs - val * ub;
9055  newrhs += newval * ub;
9056 
9057  if( !SCIPisSumRelEQ(scip, newval, val) )
9058  {
9059  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9060  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9061  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9062 
9063  /* update the coefficient and the activity bounds */
9064  if( SCIPisZero(scip, newval) )
9065  {
9066  SCIP_CALL( delCoefPos(scip, cons, i) );
9067  i--;
9068  }
9069  else
9070  {
9071  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9072  }
9073  (*nchgcoefs)++;
9074 
9075  /* get the new minimal and maximal activity of the constraint */
9076  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9077 
9078  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9079  {
9080  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9081 
9082  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9083  (*nchgsides)++;
9084  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9085  }
9086 
9087  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9088  {
9089  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9090 
9091  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9092  (*nchgsides)++;
9093  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9094  }
9095  }
9096  }
9097  else
9098  {
9099  if( !SCIPisInfinity(scip, -minleftactivity) )
9100  {
9101  assert(!SCIPisInfinity(scip, val));
9102  assert(!SCIPisInfinity(scip, lb));
9103  if( SCIPisInfinity(scip, -lb) )
9104  minleftactivity = -SCIPinfinity(scip);
9105  else
9106  minleftactivity += val * lb;
9107  }
9108 
9109  if( !SCIPisInfinity(scip, maxleftactivity) )
9110  {
9111  assert(!SCIPisInfinity(scip, val));
9112  assert(!SCIPisInfinity(scip, -ub));
9113  if( SCIPisInfinity(scip,ub) )
9114  maxleftactivity = SCIPinfinity(scip);
9115  else
9116  maxleftactivity += val * ub;
9117  }
9118  }
9119  }
9120  else
9121  {
9122  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9124  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9125  {
9126  /* change coefficients:
9127  * ai' := min(rhs - maxact, minact - lhs)
9128  * lhs' := lhs - (ai - ai')*ui
9129  * rhs' := rhs - (ai - ai')*li
9130  */
9131 
9132  lval = minactivity - consdata->lhs;
9133  rval = consdata->rhs - maxactivity;
9134 
9135  /* Try to avoid cancellation, if there are only two variables */
9136  if( consdata->nvars == 2 )
9137  {
9138  SCIP_Real otherval;
9139  otherval = consdata->vals[1-i];
9140 
9141  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
9142  {
9143  lval = val*ub - consdata->lhs;
9144  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9145  }
9146 
9147  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
9148  {
9149  rval = consdata->rhs - val*lb;
9150  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9151  }
9152  }
9153 
9154  newval = MIN(lval, rval);
9155  assert(SCIPisSumRelGE(scip, newval, val));
9156 
9157  /* Try to avoid cancellation in computation of lhs/rhs */
9158  newlhs = consdata->lhs - val * ub;
9159  newlhs += newval * ub;
9160  newrhs = consdata->rhs - val * lb;
9161  newrhs += newval * lb;
9162 
9163  if( !SCIPisSumRelEQ(scip, newval, val) )
9164  {
9165  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9166  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9167  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9168 
9169  /* update the coefficient and the activity bounds */
9170  if( SCIPisZero(scip, newval) )
9171  {
9172  SCIP_CALL( delCoefPos(scip, cons, i) );
9173  i--;
9174  }
9175  else
9176  {
9177  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9178  }
9179  (*nchgcoefs)++;
9180 
9181  /* get the new minimal and maximal activity of the constraint */
9182  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9183 
9184  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9185  {
9186  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9187 
9188  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9189  (*nchgsides)++;
9190  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9191  }
9192 
9193  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9194  {
9195  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9196 
9197  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9198  (*nchgsides)++;
9199  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9200  }
9201  }
9202  }
9203  else
9204  {
9205  if( !SCIPisInfinity(scip, -minleftactivity) )
9206  {
9207  assert(!SCIPisInfinity(scip, -val));
9208  assert(!SCIPisInfinity(scip, -ub));
9209  if( SCIPisInfinity(scip, ub) )
9210  minleftactivity = -SCIPinfinity(scip);
9211  else
9212  minleftactivity += val * ub;
9213  }
9214 
9215  if( !SCIPisInfinity(scip, maxleftactivity) )
9216  {
9217  assert(!SCIPisInfinity(scip, -val));
9218  assert(!SCIPisInfinity(scip, lb));
9219  if( SCIPisInfinity(scip, -lb) )
9220  maxleftactivity = SCIPinfinity(scip);
9221  else
9222  maxleftactivity += val * lb;
9223  }
9224  }
9225  }
9226  ++i;
9227  }
9228 
9229  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9230  minleftactivity, consdata->rhs);
9231  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9232  maxleftactivity, consdata->lhs);
9233 
9234  /* minleft == \infty ==> minactivity == \infty */
9235  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9236  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9237 
9238  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9239  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9240  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9241  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9242  */
9243  assert(!SCIPisInfinity(scip, minactivity));
9244  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9245  return SCIP_OKAY;
9246 
9247  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9248  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9249  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9250  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9251  */
9252  assert(!SCIPisInfinity(scip, -maxactivity));
9253  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9254  return SCIP_OKAY;
9255 
9256  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9257  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9258  */
9259  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9260  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9261 
9262  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9263  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9264  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9265  * they can be removed from the constraint.
9266  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9267  */
9268  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9269  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9270  {
9271  SCIP_Real minleftactivitypart;
9272  SCIP_Real maxleftactivitypart;
9273 
9274  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9275 
9276  /* try to remove redundant variables from constraint */
9277  i = 0;
9278  while( i < consdata->nvars )
9279  {
9280  var = consdata->vars[i];
9281  minleftactivitypart = 0.0;
9282  maxleftactivitypart = 0.0;
9283  lb = SCIPvarGetLbLocal(var);
9284  ub = SCIPvarGetUbLocal(var);
9285 
9286  /* get coefficient and variable's bounds */
9287  val = consdata->vals[i];
9288  assert(!SCIPisZero(scip, val));
9289 
9290  /* check sign of coefficient */
9291  if( val >= 0.0 )
9292  {
9293  /* negation of condition above in case of positive val */
9294  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9295  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9296  {
9297  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9298  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9299  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9300  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9301 
9302  minleftactivitypart = val * lb;
9303  maxleftactivitypart = val * ub;
9304 
9305  SCIP_CALL( delCoefPos(scip, cons, i) );
9306  i--;
9307 
9308  /* get the new minimal and maximal activity of the constraint */
9309  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9310 
9311  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9312  * huge contributions
9313  */
9314  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9315  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9316  }
9317  }
9318  else
9319  {
9320  /* negation of condition above in case of negative val */
9321  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9322  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9323  {
9324  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9325  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9326 
9327  minleftactivitypart = val * ub;
9328  maxleftactivitypart = val * lb;
9329 
9330  SCIP_CALL( delCoefPos(scip, cons, i) );
9331  i--;
9332 
9333  /* get the new minimal and maximal activity of the constraint */
9334  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9335 
9336  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9337  * huge contributions
9338  */
9339  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9340  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9341  }
9342  }
9343 
9344  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9345  * redundant variables could get deleted,
9346  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9347  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9348  * we would also delete y2 and as a result we would have gotten infeasibility */
9349  /* adjust lhs and right hand side */
9350  newlhs = consdata->lhs - minleftactivitypart;
9351  newrhs = consdata->rhs - maxleftactivitypart;
9352 
9353  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9354  {
9355  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9356  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9357  ++(*nchgsides);
9358  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9359  }
9360  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9361  {
9362  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9363  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9364  ++(*nchgsides);
9365  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9366  }
9367  ++i;
9368  }
9369  }
9370 
9371  return SCIP_OKAY;
9372 }
9373 
9374 /* processes equality with only one variable by fixing the variable and deleting the constraint */
9375 static
9377  SCIP* scip, /**< SCIP data structure */
9378  SCIP_CONS* cons, /**< linear constraint */
9379  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9380  int* nfixedvars, /**< pointer to count number of fixed variables */
9381  int* ndelconss /**< pointer to count number of deleted constraints */
9382  )
9383 {
9384  SCIP_CONSDATA* consdata;
9385  SCIP_VAR* var;
9386  SCIP_Real val;
9387  SCIP_Real fixval;
9388  SCIP_Bool infeasible;
9389  SCIP_Bool fixed;
9390 
9391  assert(scip != NULL);
9392  assert(cons != NULL);
9393  assert(cutoff != NULL);
9394  assert(nfixedvars != NULL);
9395  assert(ndelconss != NULL);
9396 
9397  consdata = SCIPconsGetData(cons);
9398  assert(consdata != NULL);
9399  assert(consdata->nvars == 1);
9400  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9401 
9402  /* calculate the value to fix the variable to */
9403  var = consdata->vars[0];
9404  val = consdata->vals[0];
9405  assert(!SCIPisZero(scip, val));
9406  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9407  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9408  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9409  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9410 
9411  /* fix variable */
9412  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9413  if( infeasible )
9414  {
9415  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9416  *cutoff = TRUE;
9417  return SCIP_OKAY;
9418  }
9419  if( fixed )
9420  (*nfixedvars)++;
9421 
9422  /* disable constraint */
9423  SCIP_CALL( SCIPdelCons(scip, cons) );
9424  if( !consdata->upgraded )
9425  (*ndelconss)++;
9426 
9427  return SCIP_OKAY;
9428 }
9429 
9430 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9431 static
9433  SCIP* scip, /**< SCIP data structure */
9434  SCIP_CONS* cons, /**< linear constraint */
9435  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9436  int* naggrvars, /**< pointer to count number of aggregated variables */
9437  int* ndelconss /**< pointer to count number of deleted constraints */
9438  )
9439 {
9440  SCIP_CONSDATA* consdata;
9441  SCIP_Bool infeasible;
9442  SCIP_Bool redundant;
9443  SCIP_Bool aggregated;
9444 
9445  assert(scip != NULL);
9446  assert(cons != NULL);
9447  assert(cutoff != NULL);
9448  assert(naggrvars != NULL);
9449  assert(ndelconss != NULL);
9450 
9451  consdata = SCIPconsGetData(cons);
9452  assert(consdata != NULL);
9453  assert(consdata->nvars == 2);
9454  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9455 
9456  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9457  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9458  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9459 
9460  /* aggregate the equality */
9461  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9462  consdata->rhs, &infeasible, &redundant, &aggregated) );
9463 
9464  /* check for infeasibility of aggregation */
9465  if( infeasible )
9466  {
9467  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9468  *cutoff = TRUE;
9469  return SCIP_OKAY;
9470  }
9471 
9472  /* count the aggregation */
9473  if( aggregated )
9474  (*naggrvars)++;
9475 
9476  /* delete the constraint, if it is redundant */
9477  if( redundant )
9478  {
9479  SCIP_CALL( SCIPdelCons(scip, cons) );
9480 
9481  if( !consdata->upgraded )
9482  (*ndelconss)++;
9483  }
9484 
9485  return SCIP_OKAY;
9486 }
9487 
9488 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9489 static
9491  SCIP* scip, /**< SCIP data structure */
9492  SCIP_CONSDATA* consdata, /**< linear constraint data */
9493  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9494  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9495  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9496  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9497  )
9498 {
9499  SCIP_Real slackvarlb;
9500  SCIP_Real slackvarub;
9501 
9502  assert(scip != NULL);
9503  assert(consdata != NULL);
9504  assert(newlhs != NULL);
9505  assert(newrhs != NULL);
9506  assert(!SCIPisInfinity(scip, -consdata->lhs));
9507  assert(!SCIPisInfinity(scip, consdata->rhs));
9508 
9509  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9510  slackvarub = SCIPvarGetUbGlobal(slackvar);
9511  if( slackcoef > 0.0 )
9512  {
9513  if( SCIPisInfinity(scip, -slackvarlb) )
9514  *newrhs = SCIPinfinity(scip);
9515  else
9516  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9517  if( SCIPisInfinity(scip, slackvarub) )
9518  *newlhs = -SCIPinfinity(scip);
9519  else
9520  *newlhs = consdata->lhs - slackcoef * slackvarub;
9521  }
9522  else
9523  {
9524  if( SCIPisInfinity(scip, -slackvarlb) )
9525  *newlhs = -SCIPinfinity(scip);
9526  else
9527  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9528  if( SCIPisInfinity(scip, slackvarub) )
9529  *newrhs = SCIPinfinity(scip);
9530  else
9531  *newrhs = consdata->lhs - slackcoef * slackvarub;
9532  }
9533  assert(SCIPisLE(scip, *newlhs, *newrhs));
9534 }
9535 
9536 #define MAXMULTIAGGRQUOTIENT 1e+03
9537 
9538 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9539  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9540  * is implicitly integral by this constraint
9541  *
9542  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9543  * can help.
9544  */
9545 static
9547  SCIP* scip, /**< SCIP data structure */
9548  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9549  SCIP_CONS* cons, /**< linear constraint */
9550  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9551  int* naggrvars, /**< pointer to count number of aggregated variables */
9552  int* ndelconss /**< pointer to count number of deleted constraints */
9553  )
9554 {
9555  SCIP_CONSDATA* consdata;
9556  SCIP_VAR** vars;
9557  SCIP_Real* vals;
9558  SCIP_VARTYPE bestslacktype;
9559  SCIP_VARTYPE slacktype;
9560  SCIP_Real lhs;
9561  SCIP_Real rhs;
9562  SCIP_Real bestslackdomrng;
9563  SCIP_Real minabsval;
9564  SCIP_Real maxabsval;
9565  SCIP_Bool bestremovescons;
9566  SCIP_Bool coefszeroone;
9567  SCIP_Bool coefsintegral;
9568  SCIP_Bool varsintegral;
9569  SCIP_Bool infeasible;
9570  SCIP_Bool samevar;
9571  int supinf; /* counter for infinite contributions to the supremum of a possible
9572  * multi-aggregation
9573  */
9574  int infinf; /* counter for infinite contributions to the infimum of a possible
9575  * multi-aggregation
9576  */
9577  int maxnlocksstay;
9578  int maxnlocksremove;
9579  int bestslackpos;
9580  int bestnlocks;
9581  int ncontvars;
9582  int contvarpos;
9583  int nintvars;
9584  int nimplvars;
9585  int intvarpos;
9586  int v;
9587 
9588  assert(scip != NULL);
9589  assert(cons != NULL);
9590  assert(cutoff != NULL);
9591  assert(naggrvars != NULL);
9592 
9593  consdata = SCIPconsGetData(cons);
9594  assert(consdata != NULL);
9595  assert(consdata->nvars > 2);
9596  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9597 
9598  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9599 
9600  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9601  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9602  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9603  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9604  */
9605  lhs = consdata->lhs;
9606  rhs = consdata->rhs;
9607  maxnlocksstay = 0;
9608  if( consdata->nvars == 3 )
9609  {
9610  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9611  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9612  */
9613  maxnlocksremove = 3;
9614  }
9615  else if( consdata->nvars == 4 )
9616  {
9617  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9618  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9619  */
9620  maxnlocksremove = 2;
9621  }
9622  else
9623  {
9624  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9625  maxnlocksremove = 1;
9626  }
9627 
9628  /* the locks on this constraint can be ignored */
9629  if( SCIPconsIsChecked(cons) )
9630  {
9631  if( !SCIPisInfinity(scip, -lhs) )
9632  {
9633  maxnlocksstay++;
9634  maxnlocksremove++;
9635  }
9636  if( !SCIPisInfinity(scip, rhs) )
9637  {
9638  maxnlocksstay++;
9639  maxnlocksremove++;
9640  }
9641  }
9642 
9643  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9644  vars = consdata->vars;
9645  vals = consdata->vals;
9646  bestslackpos = -1;
9647  bestslacktype = SCIP_VARTYPE_BINARY;
9648  bestnlocks = INT_MAX;
9649  bestremovescons = FALSE;
9650  bestslackdomrng = 0.0;
9651  coefszeroone = TRUE;
9652  coefsintegral = TRUE;
9653  varsintegral = TRUE;
9654  ncontvars = 0;
9655  contvarpos = -1;
9656  nintvars = 0;
9657  nimplvars = 0;
9658  intvarpos = -1;
9659  minabsval = SCIPinfinity(scip);
9660  maxabsval = -1.0;
9661  for( v = 0; v < consdata->nvars; ++v )
9662  {
9663  SCIP_VAR* var;
9664  SCIP_Real val;
9665  SCIP_Real absval;
9666  SCIP_Real varlb;
9667  SCIP_Real varub;
9668  SCIP_Bool iscont;
9669  int nlocks;
9670 
9671  assert(vars != NULL);
9672  assert(vals != NULL);
9673 
9674  var = vars[v];
9675  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9676  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9677  varlb = SCIPvarGetLbGlobal(var);
9678  varub = SCIPvarGetUbGlobal(var);
9679 
9680  val = vals[v];
9681  absval = REALABS(val);
9682  assert(SCIPisPositive(scip, absval));
9683 
9684  /* calculate minimal and maximal absolute value */
9685  if( absval < minabsval )
9686  minabsval = absval;
9687  if( absval > maxabsval )
9688  maxabsval = absval;
9689 
9690  /* do not try to multi aggregate, when numerical bad */
9691  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
9692  return SCIP_OKAY;
9693 
9694  slacktype = SCIPvarGetType(var);
9695  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9696  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9697  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9698  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9699 
9700  /* update candidates for continuous -> implint and integer -> implint conversion */
9701  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9702  {
9703  ncontvars++;
9704  contvarpos = v;
9705  }
9706  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9707  {
9708  ++nimplvars;
9709  }
9710  else if( slacktype == SCIP_VARTYPE_INTEGER )
9711  {
9712  nintvars++;
9713  intvarpos = v;
9714  }
9715 
9716  /* check, if variable is already fixed or aggregated */
9717  if( !SCIPvarIsActive(var) )
9718  continue;
9719 
9720  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9722 
9723  if( nlocks > maxnlocksremove )
9724  continue;
9725 
9726  /* check, if variable can be used as a slack variable */
9727  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9728  !SCIPdoNotMultaggrVar(scip, var) )
9729  {
9730  SCIP_Bool better;
9731  SCIP_Bool equal;
9732  SCIP_Real slackdomrng;
9733 
9734  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9735  slackdomrng = SCIPinfinity(scip);
9736  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9737  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9738  return SCIP_OKAY;
9739  else
9740  {
9741  slackdomrng = (varub - varlb)*absval;
9742  assert(!SCIPisInfinity(scip, slackdomrng));
9743  }
9744  equal = FALSE;
9745  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9746  if( !better && slacktype == bestslacktype )
9747  {
9748  better = (nlocks < bestnlocks);
9749  if( nlocks == bestnlocks && !bestremovescons )
9750  {
9751  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9752  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9753  }
9754  }
9755 
9756  if( better || equal )
9757  {
9758  SCIP_Real minresactivity;
9759  SCIP_Real maxresactivity;
9760  SCIP_Real newlhs;
9761  SCIP_Real newrhs;
9762  SCIP_Bool removescons;
9763  SCIP_Bool minisrelax;
9764  SCIP_Bool maxisrelax;
9765  SCIP_Bool isminsettoinfinity;
9766  SCIP_Bool ismaxsettoinfinity;
9767 
9768  /* check if the constraint becomes redundant after multi-aggregation */
9769  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9770  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9771 
9772  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9773  * activity
9774  */
9775  if( minisrelax || maxisrelax )
9776  continue;
9777 
9778  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9779  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9780 
9781  /* check resactivities for reliability */
9782  if( removescons )
9783  {
9784  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9785  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9786 
9787  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9788  && SCIPisFeasLE(scip, newlhs, minresactivity))
9789  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9790 
9791  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9792  }
9793 
9794  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9795  if( conshdlrdata->multaggrremove && !removescons )
9796  continue;
9797 
9798  /* prefer variables that make the constraints redundant */
9799  if( bestremovescons && !removescons )
9800  continue;
9801 
9802  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9803  * other constraints
9804  */
9805  if( !removescons && nlocks > maxnlocksstay )
9806  continue;
9807 
9808  better = better || (!bestremovescons && removescons);
9809  if( better )
9810  {
9811  bestslackpos = v;
9812  bestslacktype = slacktype;
9813  bestnlocks = nlocks;
9814  bestslackdomrng = slackdomrng;
9815  bestremovescons = removescons;
9816  }
9817  }
9818  }
9819  }
9820 
9821  /* if all coefficients and variables are integral, the right hand side must also be integral */
9822  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9823  {
9824  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9825  SCIPdebugPrintCons(scip, cons, NULL);
9826  *cutoff = TRUE;
9827  return SCIP_OKAY;
9828  }
9829 
9830  supinf = 0;
9831  infinf = 0;
9832  samevar = FALSE;
9833 
9834  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9835  for( v = 0; v < consdata->nvars; ++v )
9836  {
9837  if( v != bestslackpos )
9838  {
9839  if( SCIPisPositive(scip, consdata->vals[v]) )
9840  {
9841  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9842  {
9843  ++supinf;
9844  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9845  {
9846  ++infinf;
9847  samevar = TRUE;
9848  }
9849  }
9850  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9851  ++infinf;
9852  }
9853  else if( SCIPisNegative(scip, consdata->vals[v]) )
9854  {
9855  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9856  {
9857  ++supinf;
9858  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9859  {
9860  ++infinf;
9861  samevar = TRUE;
9862  }
9863  }
9864  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9865  ++infinf;
9866  }
9867  }
9868  }
9869  assert(!samevar || (supinf > 0 && infinf > 0));
9870 
9871  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9872  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9873  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9874  {
9875  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9876  return SCIP_OKAY;
9877  }
9878 
9879  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9880  * we cannot aggregate the variable, because the integrality condition would get lost
9881  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9882  * loose the integrality condition for this variable.
9883  */
9884  if( bestslackpos >= 0
9885  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9886  || (coefsintegral && varsintegral && nimplvars == 0)) )
9887  {
9888  SCIP_VAR* slackvar;
9889  SCIP_Real* scalars;
9890  SCIP_Real slackcoef;
9891  SCIP_Real aggrconst;
9892  SCIP_Real newlhs;
9893  SCIP_Real newrhs;
9894  SCIP_Bool aggregated;
9895 
9896  /* we found a slack variable that only occurs in at most one other constraint:
9897  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9898  */
9899  assert(bestslackpos < consdata->nvars);
9900 
9901  /* do not multi aggregate binary variables */
9902  if( SCIPvarIsBinary(vars[bestslackpos]) )
9903  return SCIP_OKAY;
9904 
9905  /* convert equality into inequality by deleting the slack variable:
9906  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9907  */
9908  slackvar = vars[bestslackpos];
9909  slackcoef = vals[bestslackpos];
9910  assert(!SCIPisZero(scip, slackcoef));
9911  aggrconst = consdata->rhs/slackcoef;
9912 
9913  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9914  assert(SCIPisLE(scip, newlhs, newrhs));
9915  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9916  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9917  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9918 
9919  /* allocate temporary memory */
9920  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9921 
9922  /* set up the multi-aggregation */
9923  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9924  for( v = 0; v < consdata->nvars; ++v )
9925  {
9926  scalars[v] = -consdata->vals[v]/slackcoef;
9927  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9928  }
9929  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9930  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9931  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9932 
9933  /* perform the multi-aggregation */
9934  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9935  &infeasible, &aggregated) );
9936  assert(aggregated);
9937 
9938  /* free temporary memory */
9939  SCIPfreeBufferArray(scip, &scalars);
9940 
9941  /* check for infeasible aggregation */
9942  if( infeasible )
9943  {
9944  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9945  *cutoff = TRUE;
9946  return SCIP_OKAY;
9947  }
9948 
9949  (*naggrvars)++;
9950 
9951  /* delete the constraint if it became redundant */
9952  if( bestremovescons )
9953  {
9954  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9955  SCIP_CALL( SCIPdelCons(scip, cons) );
9956 
9957  if( !consdata->upgraded )
9958  (*ndelconss)++;
9959  }
9960  }
9961  else if( ncontvars == 1 )
9962  {
9963  SCIP_VAR* var;
9964 
9965  assert(0 <= contvarpos && contvarpos < consdata->nvars);
9966  var = vars[contvarpos];
9967  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
9968 
9969  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9970  {
9971  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
9972  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9973  {
9974  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9975  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
9976  SCIPconsGetName(cons), SCIPvarGetName(var));
9977  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9978  if( infeasible )
9979  {
9980  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9981  *cutoff = TRUE;
9982 
9983  return SCIP_OKAY;
9984  }
9985  }
9986  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
9987  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9988  else if( !SCIPdoNotAggr(scip) )
9989  {
9990  SCIP_VAR* newvar;
9991  SCIP_Real absval;
9992  char newvarname[SCIP_MAXSTRLEN];
9993  SCIP_Bool redundant;
9994  SCIP_Bool aggregated;
9995 
9996  absval = REALABS(vals[contvarpos]);
9997 
9998  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
9999 
10000  /* create new implicit variable for aggregation */
10001  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10003 
10004  /* add new variable to problem */
10005  SCIP_CALL( SCIPaddVar(scip, newvar) );
10006 
10007 #ifdef WITH_DEBUG_SOLUTION
10008  if( SCIPdebugIsMainscip(scip) )
10009  {
10010  SCIP_Real varval;
10011  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10012  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10013  }
10014 #endif
10015 
10016  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10017  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10018  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10019 
10020  /* aggregate continuous and implicit variable */
10021  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10022 
10023  if( infeasible )
10024  {
10025  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10026  SCIPvarGetName(var), SCIPvarGetName(newvar));
10027  *cutoff = TRUE;
10028 
10029  /* release implicit variable */
10030  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10031 
10032  return SCIP_OKAY;
10033  }
10034 
10035  /* release implicit variable */
10036  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10037 
10038  if( aggregated )
10039  (*naggrvars)++;
10040  else
10041  return SCIP_OKAY;
10042  }
10043 
10044  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10045  * again
10046  */
10047  consdata->boundstightened = 0;
10048  consdata->rangedrowpropagated = 0;
10049  consdata->presolved = FALSE;
10050  }
10051  }
10052  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10053  {
10054  SCIP_VAR* var;
10055 
10056  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10057  * -> we don't convert integers into implints if the row is a 0/1-row
10058  */
10059  assert(varsintegral);
10060  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10061  var = vars[intvarpos];
10062  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10063 
10064  if( coefsintegral
10065  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10066  && SCIPisFeasIntegral(scip, consdata->rhs) )
10067  {
10068  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10069  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10070  SCIPconsGetName(cons), SCIPvarGetName(var));
10071  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10072  if( infeasible )
10073  {
10074  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10075  *cutoff = TRUE;
10076 
10077  return SCIP_OKAY;
10078  }
10079  }
10080  }
10081 
10082  return SCIP_OKAY;
10083 }
10084 
10085 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10086 static
10088  SCIP* scip, /**< SCIP data structure */
10089  SCIP_CONSDATA* consdata, /**< linear constraint data */
10090  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10091  * objective function */
10092  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10093  * this constraint */
10094  )
10095 {
10096  SCIP_VAR** vars;
10097  SCIP_VAR* var;
10098  SCIP_Real objval;
10099  SCIP_Bool negated;
10100  int nvars;
10101  int v;
10102 
10103  vars = consdata->vars;
10104  nvars = consdata->nvars;
10105 
10106  assert(vars != NULL);
10107 
10108  for( v = 0; v < nvars; ++v )
10109  {
10110  negated = FALSE;
10111  var = vars[v];
10112  assert(var != NULL);
10113 
10114  if( SCIPvarIsNegated(var) )
10115  {
10116  negated = TRUE;
10117  var = SCIPvarGetNegatedVar(var);
10118  assert(var != NULL);
10119  }
10120 
10121  objval = SCIPvarGetObj(var);
10122 
10123  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10124  * function
10125  */
10126  if( SCIPisZero(scip, objval) )
10127  return FALSE;
10128  else
10129  {
10130  SCIP_Real val;
10131 
10132  val = consdata->vals[v];
10133 
10134  if( negated )
10135  {
10136  if( v == 0 )
10137  {
10138  /* the first variable defines the scale */
10139  (*scale) = val / -objval;
10140 
10141  (*offset) += val;
10142  }
10143  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10144  (*offset) += val;
10145  else
10146  return FALSE;
10147  }
10148  else if( v == 0 )
10149  {
10150  /* the first variable defines the scale */
10151  (*scale) = val / objval;
10152  }
10153  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10154  return FALSE;
10155  }
10156  }
10157 
10158  return TRUE;
10159 }
10160 
10161 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10162  * objective coefficients and add an objective offset
10163  */
10164 static
10166  SCIP* scip, /**< SCIP data structure */
10167  SCIP_CONS* cons, /**< linear equation constraint */
10168  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10169  )
10170 {
10171  SCIP_CONSDATA* consdata;
10172  SCIP_Real offset;
10173  SCIP_Real scale;
10174  SCIP_Bool applicable;
10175  int nobjvars;
10176  int nvars;
10177  int v;
10178 
10179  assert(scip != NULL);
10180  assert(cons != NULL);
10181  assert(conshdlrdata != NULL);
10183  consdata = SCIPconsGetData(cons);
10184  assert(consdata != NULL);
10185  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10186 
10187  nvars = consdata->nvars;
10188  nobjvars = SCIPgetNObjVars(scip);
10189 
10190  /* check if the linear equality constraints does not have more variables than the objective function */
10191  if( nvars > nobjvars || nvars == 0 )
10192  return SCIP_OKAY;
10193 
10194  /* check for allowance of algorithm */
10195  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10196  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10197  return SCIP_OKAY;
10198 
10199  offset = consdata->rhs;
10200  scale = 1.0;
10201 
10202  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10203  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10204 
10205  if( applicable )
10206  {
10207  SCIP_VAR** vars;
10208 
10209  vars = consdata->vars;
10210  assert(vars != NULL);
10211 
10212  offset /= scale;
10213 
10214  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10215  SCIPconsGetName(cons), consdata->rhs, offset);
10216 
10217  /* set all objective coefficient to zero */
10218  for( v = 0; v < nvars; ++v )
10219  {
10220  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10221  }
10222 
10223  /* add an objective offset */
10224  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10225  }
10226 
10227  return SCIP_OKAY;
10228 }
10229 
10230 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10231 static
10233  SCIP* scip, /**< SCIP data structure */
10234  SCIP_CONS* cons, /**< constraint */
10235  SCIP_Real primalbound /**< feasible primal bound */
10236  )
10237 {
10238  SCIP_Real cutoffbound;
10239 
10240  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10241  * accepted
10242  */
10243  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10244 
10245  if( cutoffbound < SCIPgetCutoffbound(scip) )
10246  {
10247  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10248 
10249  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10250  }
10251  else
10252  {
10253  SCIP_CONSDATA* consdata;
10254 
10255  consdata = SCIPconsGetData(cons);
10256  assert(consdata != NULL);
10257 
10258  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10259  * resulted from one side
10260  */
10261  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10262  {
10263  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10264  * propagation
10265  */
10266  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10267  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10268  }
10269  }
10270 
10271  return SCIP_OKAY;
10272 }
10273 
10274 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10275  * constraint enters the LP by setting the initial and separated flag to FALSE
10276  */
10277 static
10279  SCIP* scip, /**< SCIP data structure */
10280  SCIP_CONS* cons, /**< linear constraint */
10281  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10282  )
10283 {
10284  SCIP_CONSDATA* consdata;
10285  SCIP_Real offset;
10286  SCIP_Real scale;
10287  SCIP_Bool applicable;
10288  int nobjvars;
10289  int nvars;
10290 
10291  assert(scip != NULL);
10292  assert(cons != NULL);
10293  assert(conshdlrdata != NULL);
10294 
10295  consdata = SCIPconsGetData(cons);
10296  assert(consdata != NULL);
10297 
10298  /* ignore equalities since these are covered by the method checkPartialObjective() */
10299  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10300  return SCIP_OKAY;
10301 
10302  nvars = consdata->nvars;
10303  nobjvars = SCIPgetNObjVars(scip);
10304 
10305  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10306  * initial and/or separated flag is set to FALSE
10307  */
10308  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10309  return SCIP_OKAY;
10310 
10311  offset = 0.0;
10312  scale = 1.0;
10313 
10314  /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10315  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10316  */
10317  if( nobjvars == 0 )
10318  return SCIP_OKAY;
10319 
10320  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10321  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10322 
10323  if( applicable )
10324  {
10325  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10326  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10327 
10328  if( SCIPisPositive(scip, scale) )
10329  {
10330  if( conshdlrdata->detectcutoffbound && rhsfinite )
10331  {
10332  SCIP_Real primalbound;
10333 
10334  primalbound = (consdata->rhs - offset) / scale;
10335 
10336  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10337  SCIPconsGetName(cons), primalbound);
10338 
10339  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10340  }
10341 
10342  if( conshdlrdata->detectlowerbound && lhsfinite )
10343  {
10344  SCIP_Real lowerbound;
10345 
10346  lowerbound = (consdata->lhs - offset) / scale;
10347 
10348  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10349  SCIPconsGetName(cons), lowerbound);
10350 
10351  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10352  }
10353 
10354  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10355  (conshdlrdata->detectlowerbound && !rhsfinite) )
10356  {
10357  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10358  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10359  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10360  }
10361  }
10362  else
10363  {
10364  if( conshdlrdata->detectlowerbound && rhsfinite )
10365  {
10366  SCIP_Real lowerbound;
10367 
10368  lowerbound = (consdata->rhs - offset) / scale;
10369 
10370  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10371  SCIPconsGetName(cons), lowerbound);
10372 
10373  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10374  }
10375 
10376  if( conshdlrdata->detectcutoffbound && lhsfinite )
10377  {
10378  SCIP_Real primalbound;
10379 
10380  primalbound = (consdata->lhs - offset) / scale;
10381 
10382  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10383  SCIPconsGetName(cons), primalbound);
10384 
10385  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10386  }
10387 
10388  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10389  (conshdlrdata->detectlowerbound && !lhsfinite) )
10390  {
10391  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10392  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10393  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10394  }
10395  }
10396  }
10397 
10398  return SCIP_OKAY;
10399 }
10400 
10401 /** converts special equalities */
10402 static
10404  SCIP* scip, /**< SCIP data structure */
10405  SCIP_CONS* cons, /**< linear constraint */
10406  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10407  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10408  int* nfixedvars, /**< pointer to count number of fixed variables */
10409  int* naggrvars, /**< pointer to count number of aggregated variables */
10410  int* ndelconss /**< pointer to count number of deleted constraints */
10411  )
10412 {
10413  SCIP_CONSDATA* consdata;
10414 
10415  assert(scip != NULL);
10416  assert(cons != NULL);
10417  assert(conshdlrdata != NULL);
10418  assert(cutoff != NULL);
10419  assert(nfixedvars != NULL);
10420  assert(naggrvars != NULL);
10421  assert(ndelconss != NULL);
10422 
10423  consdata = SCIPconsGetData(cons);
10424  assert(consdata != NULL);
10425  assert(consdata->removedfixings);
10426 
10427  /* do nothing on inequalities */
10428  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10429  return SCIP_OKAY;
10430 
10431  /* depending on the number of variables, call a special conversion method */
10432  if( consdata->nvars == 1 )
10433  {
10434  /* fix variable */
10435  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10436  }
10437  else if( consdata->nvars == 2 )
10438  {
10439  /* aggregate one of the variables */
10440  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10441  }
10442  else
10443  {
10444  /* check if the equality is part of the objective function */
10445  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10446 
10447  /* try to multi-aggregate one of the variables */
10448  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10449  }
10450 
10451  return SCIP_OKAY;
10452 }
10453 
10454 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10455  * integral
10456  */
10457 static
10459  SCIP* scip, /**< SCIP data structure */
10460  SCIP_CONSDATA* consdata, /**< linear constraint */
10461  int pos, /**< position of variable to be left out */
10462  SCIP_Real val /**< value to divide the coefficients by */
10463  )
10464 {
10465  int v;
10466 
10467  assert(scip != NULL);
10468  assert(consdata != NULL);
10469  assert(0 <= pos && pos < consdata->nvars);
10470 
10471  for( v = 0; v < consdata->nvars; ++v )
10472  {
10473  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10474  return FALSE;
10475  }
10476 
10477  return TRUE;
10478 }
10479 
10480 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10481  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10482  */
10483 static
10485  SCIP* scip, /**< SCIP data structure */
10486  SCIP_Real side, /**< lhs or rhs */
10487  SCIP_Real val, /**< coefficient */
10488  SCIP_Real minresactivity, /**< minimal residual activity */
10489  SCIP_Real maxresactivity, /**< maximal residual activity */
10490  SCIP_Real* minval, /**< pointer to store calculated minval */
10491  SCIP_Real* maxval /**< pointer to store calculated maxval */
10492  )
10493 {
10494  assert(scip != NULL);
10495  assert(minval != NULL);
10496  assert(maxval != NULL);
10497 
10498  if( val > 0.0 )
10499  {
10500  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10501  *minval = -maxresactivity;
10502  else
10503  *minval = (side - maxresactivity)/val;
10504 
10505  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10506  *maxval = -minresactivity;
10507  else
10508  *maxval = (side - minresactivity)/val;
10509  }
10510  else
10511  {
10512  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10513  *minval = minresactivity;
10514  else
10515  *minval = (side - minresactivity)/val;
10516 
10517  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10518  *maxval = maxresactivity;
10519  else
10520  *maxval = (side - maxresactivity)/val;
10521  }
10522 }
10523 
10524 
10525 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10526  * linear inequality
10527  */
10528 static
10530  SCIP* scip, /**< SCIP data structure */
10531  SCIP_CONS* cons, /**< linear constraint */
10532  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10533  int* nfixedvars, /**< pointer to count number of fixed variables */
10534  int* naggrvars, /**< pointer to count number of aggregated variables */
10535  int* ndelconss /**< pointer to count number of deleted constraints */
10536  )
10537 {
10538  SCIP_CONSDATA* consdata;
10539  SCIP_Bool lhsexists;
10540  SCIP_Bool rhsexists;
10541  SCIP_Bool bestisint;
10542  SCIP_Bool bestislhs;
10543  int bestpos;
10544  int i;
10545  int maxotherlocks;
10547  assert(scip != NULL);
10548  assert(cons != NULL);
10549  assert(cutoff != NULL);
10550  assert(nfixedvars != NULL);
10551  assert(naggrvars != NULL);
10552  assert(ndelconss != NULL);
10553 
10554  /* only process checked constraints (for which the locks are increased);
10555  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10556  * dualfix presolver
10557  */
10558  if( !SCIPconsIsChecked(cons) )
10559  return SCIP_OKAY;
10560 
10561  consdata = SCIPconsGetData(cons);
10562  assert(consdata != NULL);
10563 
10564  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10565  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10566 
10567  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10568  * can use it safely for aggregation and break the search loop
10569  */
10570  bestpos = -1;
10571  bestisint = TRUE;
10572  bestislhs = FALSE;
10573 
10574  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10575  * everything else would produce fill-in. Exceptions:
10576  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10577  * produced.
10578  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10579  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10580  * six nonzeros (two variables per substitution).
10581  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10582  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10583  * six nonzeros (three variables per substitution). God exists!
10584  */
10585  if( consdata->nvars <= 2 )
10586  maxotherlocks = INT_MAX;
10587  else if( consdata->nvars == 3 )
10588  maxotherlocks = 3;
10589  else if( consdata->nvars == 4 )
10590  maxotherlocks = 2;
10591  else
10592  maxotherlocks = 1;
10593 
10594  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10595  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10596  maxotherlocks++;
10597 
10598  for( i = 0; i < consdata->nvars && bestisint; ++i )
10599  {
10600  SCIP_VAR* var;
10601  SCIP_Bool isint;
10602  SCIP_Real val;
10603  SCIP_Real obj;
10604  SCIP_Real lb;
10605  SCIP_Real ub;
10606  SCIP_Bool agglhs;
10607  SCIP_Bool aggrhs;
10608 
10609  var = consdata->vars[i];
10611 
10612  /* if we already found a candidate, skip integers */
10613  if( bestpos >= 0 && isint )
10614  continue;
10615 
10616  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10617  * active, fixed, or single-aggregated with another binary variable
10618  */
10619  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10620  continue;
10621 
10622  if ( SCIPdoNotMultaggrVar(scip, var) )
10623  continue;
10624 
10625  val = consdata->vals[i];
10626  obj = SCIPvarGetObj(var);
10627  lb = SCIPvarGetLbGlobal(var);
10628  ub = SCIPvarGetUbGlobal(var);
10629 
10630  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10631  *
10632  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10633  * - constraint is the only one that forbids fixing the variable to its lower bound
10634  * - 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
10635  *
10636  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10637  * - constraint is the only one that forbids fixing the variable to its upper bound
10638  * - 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
10639  *
10640  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10641  * - constraint is the only one that forbids fixing the variable to its upper bound
10642  * - 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
10643  *
10644  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10645  * - constraint is the only one that forbids fixing the variable to its lower bound
10646  * - 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
10647  *
10648  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10649  * of all x_j
10650  * furthermore: we only want to apply this, if no fill-in will be produced
10651  */
10652  agglhs = lhsexists
10653  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10654  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10655  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10656  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10657  aggrhs = rhsexists
10658  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10659  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10660  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10661  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10662  if( agglhs || aggrhs )
10663  {
10664  SCIP_Real minresactivity;
10665  SCIP_Real maxresactivity;
10666  SCIP_Real minval;
10667  SCIP_Real maxval;
10668  SCIP_Bool minisrelax;
10669  SCIP_Bool maxisrelax;
10670  SCIP_Bool isminsettoinfinity;
10671  SCIP_Bool ismaxsettoinfinity;
10672 
10673  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10674  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10675  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10676  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10677 
10678  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10679  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10680  * This is needed, because we do not want to rely on relaxed finite resactivities.
10681  */
10682  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10683 
10684  if( agglhs )
10685  {
10686  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10687  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10688 
10689  assert(SCIPisLE(scip, minval, maxval));
10690  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10691  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10692  {
10693  SCIP_Real oldmaxresactivity;
10694  SCIP_Real oldminresactivity;
10695  SCIP_Bool recalculated;
10696 
10697  recalculated = FALSE;
10698  oldmaxresactivity = maxresactivity;
10699  oldminresactivity = minresactivity;
10700 
10701  /* check minresactivity for reliability */
10702  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10703  {
10704  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10705  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10706  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10707  }
10708 
10709  /* check maxresactivity for reliability */
10710  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10711  {
10712  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10713  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10714  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10715  }
10716 
10717  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10718  if( recalculated )
10719  {
10720  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10721 
10722  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10723  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10724 
10725  assert(SCIPisLE(scip, minval, maxval));
10726  }
10727 
10728  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10729  {
10730  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10731  * in the multi-aggregation
10732  */
10733  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10734  {
10735  bestpos = i;
10736  bestisint = isint;
10737  bestislhs = TRUE;
10738  continue; /* no need to also look at the right hand side */
10739  }
10740  }
10741  }
10742  }
10743 
10744  if( aggrhs )
10745  {
10746  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10747  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10748 
10749  assert(SCIPisLE(scip,minval,maxval));
10750  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10751  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10752  {
10753  SCIP_Real oldmaxresactivity;
10754  SCIP_Real oldminresactivity;
10755  SCIP_Bool recalculated;
10756 
10757  recalculated = FALSE;
10758  oldmaxresactivity = maxresactivity;
10759  oldminresactivity = minresactivity;
10760 
10761  /* check minresactivity for reliability */
10762  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10763  {
10764  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10765  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10766  }
10767 
10768  /* check maxresactivity for reliability */
10769  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10770  {
10771  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10772  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10773  }
10774 
10775  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10776  if( recalculated )
10777  {
10778  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10779  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10780  assert(SCIPisLE(scip,minval,maxval));
10781  }
10782 
10783  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10784  {
10785  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10786  * in the multi-aggregation
10787  */
10788  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10789  {
10790  bestpos = i;
10791  bestisint = isint;
10792  bestislhs = FALSE;
10793  }
10794  }
10795  }
10796  }
10797  }
10798  }
10799 
10800  if( bestpos >= 0 )
10801  {
10802  SCIP_VAR** aggrvars;
10803  SCIP_Real* aggrcoefs;
10804  SCIP_Real aggrconst;
10805  SCIP_VAR* bestvar;
10806  SCIP_Real bestval;
10807  SCIP_Real epsilon;
10808  int naggrs;
10809  int j;
10810  SCIP_Bool infeasible;
10811  SCIP_Bool aggregated;
10812  SCIP_Bool samevar;
10813  int supinf; /* counter for infinite contributions to the supremum of a possible
10814  * multi-aggregation
10815  */
10816  int infinf; /* counter for infinite contributions to the infimum of a possible
10817  * multi-aggregation
10818  */
10819 
10820  assert(!bestislhs || lhsexists);
10821  assert(bestislhs || rhsexists);
10822 
10823  bestvar = consdata->vars[bestpos];
10824  bestval = consdata->vals[bestpos];
10825  assert(bestisint ==
10827 
10828  /* allocate temporary memory */
10829  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10830  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10831 
10832  /* set up the multi-aggregation */
10833  SCIPdebugPrintCons(scip, cons, NULL);
10834  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10835  naggrs = 0;
10836  supinf = 0;
10837  infinf = 0;
10838  samevar = FALSE;
10839  epsilon = SCIPepsilon(scip);
10840 
10841  for( j = 0; j < consdata->nvars; ++j )
10842  {
10843  if( j != bestpos )
10844  {
10845  SCIP_Real absaggrcoef;
10846 
10847  aggrvars[naggrs] = consdata->vars[j];
10848  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10849  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10850 
10851  absaggrcoef = REALABS(aggrcoefs[naggrs]);
10852 
10853  /* do not try to multi aggregate, when numerical bad */
10854  if( absaggrcoef < epsilon )
10855  {
10856  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10857 
10858  /* free temporary memory */
10859  SCIPfreeBufferArray(scip, &aggrcoefs);
10860  SCIPfreeBufferArray(scip, &aggrvars);
10861 
10862  return SCIP_OKAY;
10863  }
10864 
10865  if( bestisint )
10866  {
10867  /* coefficient must be integral: round it to exact integral value */
10868  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10869  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10870  }
10871 
10872  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10873  {
10874  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10875  {
10876  ++supinf;
10877  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10878  {
10879  ++infinf;
10880  samevar = TRUE;
10881  }
10882  }
10883  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10884  ++infinf;
10885  }
10886  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10887  {
10888  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10889  {
10890  ++supinf;
10891  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10892  {
10893  ++infinf;
10894  samevar = TRUE;
10895  }
10896  }
10897  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10898  ++infinf;
10899  }
10900 
10901  naggrs++;
10902  }
10903  }
10904  assert(!samevar || (supinf > 0 && infinf > 0));
10905 
10906  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10907  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10908  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10909  assert(naggrs == consdata->nvars-1);
10910 
10911  /* right hand side must be integral: round it to exact integral value */
10912  if( bestisint )
10913  {
10914  assert(SCIPisIntegral(scip, aggrconst));
10915  aggrconst = SCIPfloor(scip, aggrconst+0.5);
10916  }
10917 
10918  aggregated = FALSE;
10919  infeasible = FALSE;
10920 
10921  /* perform the multi-aggregation */
10922  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
10923  {
10924  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
10925  * also convertLongEquality() early termination due to coefficients
10926  */
10927  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10928  }
10929  else
10930  {
10931  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10932  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10933  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10934  }
10935  /* free temporary memory */
10936  SCIPfreeBufferArray(scip, &aggrcoefs);
10937  SCIPfreeBufferArray(scip, &aggrvars);
10938 
10939  /* check for infeasible aggregation */
10940  if( infeasible )
10941  {
10942  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10943  *cutoff = TRUE;
10944  return SCIP_OKAY;
10945  }
10946 
10947  /* delete the constraint, if the aggregation was successful */
10948  if( aggregated )
10949  {
10950  SCIP_CALL( SCIPdelCons(scip, cons) );
10951 
10952  if( !consdata->upgraded )
10953  (*ndelconss)++;
10954  (*naggrvars)++;
10955  }
10956  else
10957  {
10958  SCIPdebugMsg(scip, "aggregation non successful!\n");
10959  }
10960  }
10961 
10962  return SCIP_OKAY;
10963 }
10964 
10965 #define BINWEIGHT 1
10966 #define INTWEIGHT 4
10967 #define CONTWEIGHT 8
10968 
10969 /** gets weight for variable in a "weighted number of variables" sum */
10970 static
10971 int getVarWeight(
10972  SCIP_VAR* var /**< variable to get weight for */
10973  )
10974 {
10975  switch( SCIPvarGetType(var) )
10976  {
10977  case SCIP_VARTYPE_BINARY:
10978  return BINWEIGHT;
10979  case SCIP_VARTYPE_INTEGER:
10980  case SCIP_VARTYPE_IMPLINT:
10981  return INTWEIGHT;
10983  return CONTWEIGHT;
10984  default:
10985  SCIPerrorMessage("invalid variable type\n");
10986  SCIPABORT();
10987  return 0; /*lint !e527*/
10988  }
10989 }
10990 
10991 /** tries to aggregate variables in equations a^Tx = lhs
10992  * in case there are at most two binary variables with an odd coefficient and all other
10993  * variables are not continuous and have an even coefficient then:
10994  * - exactly one odd binary variables
10995  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
10996  * - lhs is odd -> y = 1
10997  * - lhs is even -> y = 0
10998  * - exactly two odd binary variables
10999  * aggregate the two binary variables with odd coefficient
11000  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11001  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11002  */
11003 static
11005  SCIP* scip, /**< SCIP data structure */
11006  SCIP_CONS* cons, /**< linear constraint */
11007  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11008  int* nfixedvars, /**< pointer to count number of fixed variables */
11009  int* naggrvars, /**< pointer to count number of aggregated variables */
11010  int* ndelconss /**< pointer to count number of deleted constraints */
11011  )
11012 { /*lint --e{715}*/
11013  SCIP_CONSDATA* consdata;
11014  SCIP_Bool success;
11015 
11016  assert( scip != NULL );
11017  assert( cons != NULL );
11018 
11019  consdata = SCIPconsGetData(cons);
11020  assert( consdata != NULL );
11022  /* check if the linear constraint is an equation with integral right hand side */
11023  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11024  return SCIP_OKAY;
11025 
11026  /* try to fix and aggregated variables until nothing is possible anymore */
11027  do
11028  {
11029  int v;
11030  int nvars;
11031  SCIP_VAR** vars;
11032  SCIP_Real* vals;
11033  SCIP_Real lhs;
11034  SCIP_Bool lhsodd;
11035 
11036  SCIP_Bool infeasible;
11037  SCIP_Bool fixed;
11038  SCIP_Bool aggregated;
11039  SCIP_Bool redundant;
11040 
11041  SCIP_VAR* var1;
11042  SCIP_VAR* var2;
11043  int noddvars;
11044 
11045  success = FALSE;
11046 
11047  lhs = consdata->lhs;
11048  vars = consdata->vars;
11049  vals = consdata->vals;
11050  nvars = consdata->nvars;
11051 
11052  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11053 
11054  var1 = NULL;
11055  var2 = NULL;
11056  noddvars = 0;
11057 
11058  /* search for binary variables with an odd coefficient */
11059  for( v = 0; v < nvars && noddvars < 3; ++v )
11060  {
11061  SCIP_Longint val;
11062 
11063  /* all coefficients and variables have to be integral */
11064  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11065  return SCIP_OKAY;
11066 
11067  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11068  if( val % 2 != 0 )
11069  {
11070  /* the odd values have to belong to binary variables */
11071  if( !SCIPvarIsBinary(vars[v]) )
11072  return SCIP_OKAY;
11073 
11074  if( noddvars == 0 )
11075  var1 = vars[v];
11076  else
11077  var2 = vars[v];
11078 
11079  noddvars++;
11080  }
11081  }
11082 
11083  /* check lhs is odd or even */
11084  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11085 
11086  if( noddvars == 1 )
11087  {
11088  assert( var1 != NULL );
11089 
11090  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11091  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11092 
11093  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11094 
11095  /* check for infeasibility of fixing */
11096  if( infeasible )
11097  {
11098  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11099  *cutoff = TRUE;
11100  return SCIP_OKAY;
11101  }
11102 
11103  if( fixed )
11104  {
11105  SCIPdebugMsg(scip, " -> feasible fixing\n");
11106  (*nfixedvars)++;
11107  success = TRUE;
11108  }
11109  }
11110  else if( noddvars == 2 )
11111  {
11112  assert( var1 != NULL );
11113  assert( var2 != NULL );
11114 
11115  /* aggregate the two variables with odd coefficient
11116  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11117  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11118  */
11119  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11120  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11121 
11122  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11123  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11124 
11125  /* check for infeasibility of aggregation */
11126  if( infeasible )
11127  {
11128  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11129  *cutoff = TRUE;
11130  return SCIP_OKAY;
11131  }
11132 
11133  /* count the aggregation */
11134  if( aggregated )
11135  {
11136  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11137  (*naggrvars)++;
11138  success = TRUE;
11139  }
11140  }
11141 
11142  if( success )
11143  {
11144  /* apply fixings and aggregation to successfully rerun this presolving step */
11145  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11146 
11147  if( infeasible )
11148  {
11149  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11150  *cutoff = TRUE;
11151  return SCIP_OKAY;
11152  }
11153 
11154  /* normalize constraint */
11155  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11156 
11157  if( infeasible )
11158  {
11159  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11160  *cutoff = TRUE;
11161  return SCIP_OKAY;
11162  }
11163  }
11164  }
11165  while( success );
11166 
11167  return SCIP_OKAY;
11168 }
11169 
11170 
11171 
11172 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11173  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11174  * coefficients
11175  */
11176 static
11177 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11178 { /*lint --e{715}*/
11179  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11180  SCIP_VARTYPE vartype1;
11181  SCIP_VARTYPE vartype2;
11182  SCIP_Real value;
11183 
11184  assert(consdata != NULL);
11185  assert(0 <= ind1 && ind1 < consdata->nvars);
11186  assert(0 <= ind2 && ind2 < consdata->nvars);
11187 
11188  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11189  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11190 
11191  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11192  {
11193  /* continuous varibles will be sorted to the back */
11194  if( vartype2 != vartype1 )
11195  return +1;
11196  /* both variables are continuous */
11197  else
11198  return 0;
11199  }
11200  /* continuous variables will be sorted to the back */
11201  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11202  return -1;
11203 
11204  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11205 
11206  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11207  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11208 }
11209 
11210 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11211  * common divisor
11212  *
11213  * 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
11214  * constraint to 1^Tx = 1
11215  */
11216 static
11218  SCIP* scip, /**< SCIP data structure */
11219  SCIP_CONS* cons, /**< linear constraint */
11220  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11221  int* nchgsides /**< pointer to store the amount of changed sides */
11222  )
11223 {
11224  SCIP_CONSDATA* consdata;
11225  SCIP_VAR** vars;
11226  SCIP_Real* vals;
11227  SCIP_Real minval;
11228  SCIP_Real secondminval;
11229  SCIP_Real maxval;
11230  SCIP_Real lhs;
11231  SCIP_Real rhs;
11232  int nvars;
11233  int v;
11235  /* we must not change a modifiable constraint in any way */
11236  if( SCIPconsIsModifiable(cons) )
11237  return SCIP_OKAY;
11238 
11239  if( SCIPconsIsDeleted(cons) )
11240  return SCIP_OKAY;
11241 
11242  consdata = SCIPconsGetData(cons);
11243  assert(consdata != NULL);
11244 
11245  nvars = consdata->nvars;
11246 
11247  /* do not check empty or bound-constraints */
11248  if( nvars < 2 )
11249  return SCIP_OKAY;
11250 
11251  vals = consdata->vals;
11252  vars = consdata->vars;
11253  assert(vars != NULL);
11254  assert(vals != NULL);
11255 
11256  lhs = consdata->lhs;
11257  rhs = consdata->rhs;
11258  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11259  assert(!SCIPisNegative(scip, rhs));
11260 
11261  minval = SCIP_INVALID;
11262  secondminval = SCIP_INVALID;
11263  maxval = -SCIP_INVALID;
11264 
11265  for( v = nvars - 1; v >= 0; --v )
11266  {
11267  if( SCIPvarIsBinary(vars[v]) )
11268  {
11269  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11270  {
11271  secondminval = minval;
11272  minval = vals[v];
11273  }
11274  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11275  secondminval = vals[v];
11276 
11277  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11278  maxval = vals[v];
11279  }
11280  else
11281  break;
11282  }
11283 
11284  /* check if all variables are binary */
11285  if( v == -1 )
11286  {
11287  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11288  return SCIP_OKAY;
11289 
11290  /* check if we can and need to choose exactly one binary variable */
11291  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11292  {
11293  /* change all coefficients to 1.0 */
11294  for( v = nvars - 1; v >= 0; --v )
11295  {
11296  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11297  }
11298  (*nchgcoefs) += nvars;
11299 
11300  /* replace old right and left hand side with 1.0 */
11301  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11302  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11303  (*nchgsides) += 2;
11304  }
11305  }
11306 
11307  return SCIP_OKAY;
11308 }
11309 
11310 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11311  * for equations @see rangedRowSimplify() will be called
11312  *
11313  * there are several different coefficient reduction steps which will be applied
11314  *
11315  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11316  *
11317  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11318  *
11319  * 2. We try to remove redundant fractional parts in a constraint
11320  *
11321  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11322  *
11323  * 3. We are using the greatest common divisor for further reductions
11324  *
11325  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11326  * integral
11327  */
11328 static
11330  SCIP* scip, /**< SCIP data structure */
11331  SCIP_CONS* cons, /**< linear constraint */
11332  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11333  int* nchgsides, /**< pointer to store the amount of changed sides */
11334  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11335  )
11336 {
11337  SCIP_CONSDATA* consdata;
11338  SCIP_VAR** vars;
11339  SCIP_Real* vals;
11340  int* perm;
11341  SCIP_Real minactsub;
11342  SCIP_Real maxactsub;
11343  SCIP_Real siderest;
11344  SCIP_Real feastol;
11345  SCIP_Real newcoef;
11346  SCIP_Real absval;
11347  SCIP_Real side;
11348  SCIP_Real lhs;
11349  SCIP_Real rhs;
11350  SCIP_Real lb;
11351  SCIP_Real ub;
11352  SCIP_Longint restcoef;
11353  SCIP_Longint oldgcd;
11354  SCIP_Longint rest;
11355  SCIP_Longint gcd;
11356  SCIP_Bool isminsettoinfinity;
11357  SCIP_Bool ismaxsettoinfinity;
11358  SCIP_Bool isminrelax;
11359  SCIP_Bool ismaxrelax;
11360  SCIP_Bool allcoefintegral;
11361  SCIP_Bool onlybin;
11362  SCIP_Bool hasrhs;
11363  SCIP_Bool haslhs;
11364  int oldnchgcoefs;
11365  int oldnchgsides;
11366  int foundbin;
11367  int candpos;
11368  int candpos2;
11369  int offsetv;
11370  int nvars;
11371  int v;
11372  int w;
11373 
11374  assert(scip != NULL);
11375  assert(cons != NULL);
11376  assert(nchgcoefs != NULL);
11377  assert(nchgsides != NULL);
11378 
11379  *infeasible = FALSE;
11380 
11381  /* we must not change a modifiable constraint in any way */
11382  if( SCIPconsIsModifiable(cons) )
11383  return SCIP_OKAY;
11384 
11385  if( SCIPconsIsDeleted(cons) )
11386  return SCIP_OKAY;
11387 
11388  consdata = SCIPconsGetData(cons);
11389  assert(consdata != NULL);
11390 
11391  nvars = consdata->nvars;
11392 
11393  /* do not check empty or bound-constraints */
11394  if( nvars <= 2 )
11395  return SCIP_OKAY;
11396 
11397  /* update maximal activity delta if necessary */
11398  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11399  consdataRecomputeMaxActivityDelta(scip, consdata);
11400 
11401  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11402  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11403  checkMaxActivityDelta(scip, consdata);
11404 
11405  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11406  * accordingly
11407  */
11408  /* can only work with valid non-infinity activities per variable */
11409  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11410  return SCIP_OKAY;
11411 
11412  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11413  * but the eventsystem seems to be full
11414  */
11415  consdata->normalized = FALSE;
11416 
11417  /* normalize constraint */
11418  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11419  assert(nvars == consdata->nvars);
11420 
11421  if( *infeasible )
11422  return SCIP_OKAY;
11423 
11424  if( !consdata->normalized )
11425  return SCIP_OKAY;
11426 
11427  lhs = consdata->lhs;
11428  rhs = consdata->rhs;
11429  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11430  assert(!SCIPisNegative(scip, rhs));
11431 
11432  if( !SCIPisInfinity(scip, -lhs) )
11433  haslhs = TRUE;
11434  else
11435  haslhs = FALSE;
11436 
11437  if( !SCIPisInfinity(scip, rhs) )
11438  hasrhs = TRUE;
11439  else
11440  hasrhs = FALSE;
11441 
11442  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11443  SCIPdebug( oldnchgsides = *nchgsides; )
11444 
11445  /* @todo also work on ranged rows */
11446  if( haslhs && hasrhs )
11447  {
11448  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11449 
11450  return SCIP_OKAY;
11451  }
11452  assert(haslhs != hasrhs);
11453 
11454  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11455  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11456  assert(!haslhs || !SCIPisNegative(scip, lhs));
11457 
11458  /* get temporary memory to store the sorted permutation */
11459  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11460 
11461  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11462  * value of their coefficients
11463  */
11464  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11465 
11466  /* perform sorting after permutation array */
11467  permSortConsdata(consdata, perm, nvars);
11468  consdata->sorted = FALSE;
11469  consdata->binvarssorted = FALSE;
11470 
11471  vars = consdata->vars;
11472  vals = consdata->vals;
11473  assert(vars != NULL);
11474  assert(vals != NULL);
11475  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11476 
11477  /* free temporary memory */
11478  SCIPfreeBufferArray(scip, &perm);
11479 
11480  /* only check constraints with at least two non continuous variables */
11481  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11482  return SCIP_OKAY;
11483 
11484  /* do not process constraints when all coefficients are 1.0 */
11485  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11486  return SCIP_OKAY;
11487 
11488  feastol = SCIPfeastol(scip);
11489 
11490  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11491  SCIPdebugPrintCons(scip, cons, NULL);
11492 
11493  /* get global activities */
11494  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11495  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11496 
11497  /* cannot work with infinite activities */
11498  if( isminsettoinfinity || ismaxsettoinfinity )
11499  return SCIP_OKAY;
11500 
11501  assert(!isminrelax);
11502  assert(!ismaxrelax);
11503  assert(maxactsub > minactsub);
11504  assert(!SCIPisInfinity(scip, -minactsub));
11505  assert(!SCIPisInfinity(scip, maxactsub));
11506 
11507  v = 0;
11508  offsetv = -1;
11509  side = haslhs ? lhs : rhs;
11510 
11511  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11512  * do not need to look at the large coefficients
11513  *
11514  * e.g. all x are binary, z are positive integer
11515  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11516  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11517  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11518  *
11519  * can be changed to
11520  *
11521  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11522  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11523  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11524  */
11525 
11526  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11527  * hand side, we cannot apply the extra reduction step and need to reset v
11528  *
11529  * 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
11530  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11531  * for all i is a solution
11532  *
11533  * also redundancy of variables would not be correctly determined in such a case
11534  */
11535  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11536  {
11537  v = 1;
11538 
11539  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11540  {
11541  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11542  * extra step, which might have worked
11543  */
11544  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11545  {
11546  v = 0;
11547  break;
11548  }
11549 
11550  ++v;
11551  }
11552 
11553  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11554  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11555  if( v == nvars )
11556  return SCIP_OKAY;
11557 
11558  /* cannot work with continuous variables which have a big coefficient */
11559  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11560  return SCIP_OKAY;
11561 
11562  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11563  if( SCIPisEQ(scip, side, -vals[v]) )
11564  v = 0;
11565 
11566  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11567  * reduction
11568  */
11569  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11570  v = 0;
11571 
11572  if( v > 0 )
11573  {
11574  assert(v < nvars);
11575 
11576  offsetv = v - 1;
11577 
11578  for( w = 0; w < v; ++w )
11579  {
11580  lb = SCIPvarGetLbGlobal(vars[w]);
11581  ub = SCIPvarGetUbGlobal(vars[w]);
11582 
11583  assert(vals[w] > 0);
11584 
11585  /* update residual activities */
11586  maxactsub -= ub * vals[w];
11587  minactsub -= lb * vals[w];
11588  assert(maxactsub > minactsub);
11589  }
11590  }
11591  }
11592 
11593  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11594  *
11595  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11596  *
11597  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11598  * to
11599  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11600  */
11601  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11602  {
11603  SCIP_Bool redundant = FALSE;
11604 
11605  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11606  assert(gcd >= 1);
11607 
11608  if( v == 0 )
11609  {
11610  lb = SCIPvarGetLbGlobal(vars[0]);
11611  ub = SCIPvarGetUbGlobal(vars[0]);
11612 
11613  /* update residual activities */
11614  if( vals[0] > 0 )
11615  {
11616  maxactsub -= ub * vals[0];
11617  minactsub -= lb * vals[0];
11618  }
11619  else
11620  {
11621  maxactsub -= lb * vals[0];
11622  minactsub -= ub * vals[0];
11623  }
11624  assert(maxactsub > minactsub);
11625  ++v;
11626  }
11627 
11628  siderest = -SCIP_INVALID;
11629  allcoefintegral = TRUE;
11630 
11631  /* check if some variables always fit into the given constraint */
11632  for( ; v < nvars - 1; ++v )
11633  {
11634  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11635  break;
11636 
11637  if( !SCIPisIntegral(scip, vals[v]) )
11638  {
11639  allcoefintegral = FALSE;
11640  break;
11641  }
11642 
11643  /* calculate greatest common divisor for all general and binary variables */
11644  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11645 
11646  if( gcd == 1 )
11647  break;
11648 
11649  lb = SCIPvarGetLbGlobal(vars[v]);
11650  ub = SCIPvarGetUbGlobal(vars[v]);
11651 
11652  assert(!SCIPisInfinity(scip, -lb));
11653  assert(!SCIPisInfinity(scip, ub));
11654 
11655  /* update residual activities */
11656  if( vals[v] > 0 )
11657  {
11658  maxactsub -= ub * vals[v];
11659  minactsub -= lb * vals[v];
11660  }
11661  else
11662  {
11663  maxactsub -= lb * vals[v];
11664  minactsub -= ub * vals[v];
11665  }
11666  assert(SCIPisGE(scip, maxactsub, minactsub));
11667 
11668  if( hasrhs )
11669  {
11670  /* determine the remainder of the right hand side and the gcd */
11671  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11672  }
11673  else
11674  {
11675  /* determine the remainder of the left hand side and the gcd */
11676  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11677  if( SCIPisZero(scip, siderest) )
11678  siderest = gcd;
11679  }
11680 
11681  /* early termination if the activities deceed the gcd */
11682  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11683  {
11684  redundant = TRUE;
11685  break;
11686  }
11687  }
11688  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11689 
11690  if( !redundant )
11691  {
11692  if( hasrhs )
11693  {
11694  /* determine the remainder of the right hand side and the gcd */
11695  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11696  }
11697  else
11698  {
11699  /* determine the remainder of the left hand side and the gcd */
11700  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11701  if( SCIPisZero(scip, siderest) )
11702  siderest = gcd;
11703  }
11704  }
11705  else
11706  ++v;
11707 
11708  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",
11709  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11710 
11711  /* check if we can remove redundant variables */
11712  if( v < nvars && (redundant ||
11713  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11714  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11715  {
11716  SCIP_Real oldcoef;
11717 
11718  /* double check the redundancy */
11719 #ifndef NDEBUG
11720  SCIP_Real tmpminactsub = 0.0;
11721  SCIP_Real tmpmaxactsub = 0.0;
11722 
11723  /* recompute residual activities */
11724  for( w = v; w < nvars; ++w )
11725  {
11726  lb = SCIPvarGetLbGlobal(vars[w]);
11727  ub = SCIPvarGetUbGlobal(vars[w]);
11728 
11729  assert(!SCIPisInfinity(scip, -lb));
11730  assert(!SCIPisInfinity(scip, ub));
11731 
11732  /* update residual activities */
11733  if( vals[w] > 0 )
11734  {
11735  tmpmaxactsub += ub * vals[w];
11736  tmpminactsub += lb * vals[w];
11737  }
11738  else
11739  {
11740  tmpmaxactsub += lb * vals[w];
11741  tmpminactsub += ub * vals[w];
11742  }
11743  assert(tmpmaxactsub >= tmpminactsub);
11744  }
11745 
11746  if( hasrhs )
11747  {
11748  assert(offsetv == -1);
11749 
11750  /* determine the remainder of the right hand side and the gcd */
11751  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11752  }
11753  else
11754  {
11755  /* determine the remainder of the left hand side and the gcd */
11756  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11757  if( SCIPisZero(scip, siderest) )
11758  siderest = gcd;
11759  }
11760 
11761  /* does the redundancy really is fulfilled */
11762  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11763 #endif
11764 
11765  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11766  nvars - v, SCIPconsGetName(cons));
11767 
11768  /* remove redundant variables */
11769  for( w = nvars - 1; w >= v; --w )
11770  {
11771  SCIP_CALL( delCoefPos(scip, cons, w) );
11772  }
11773  (*nchgcoefs) += (nvars - v);
11774 
11775  assert(w >= 0);
11776 
11777  oldcoef = vals[w];
11778 
11779  /* normalize constraint */
11780  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11781  assert(vars == consdata->vars);
11782  assert(vals == consdata->vals);
11783  assert(w < consdata->nvars);
11784 
11785  if( *infeasible )
11786  return SCIP_OKAY;
11787 
11788  /* compute new greatest common divisor due to normalization */
11789  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11790  assert(gcd >= 1);
11791 
11792  /* update side */
11793  if( hasrhs )
11794  {
11795  /* replace old with new right hand side */
11796  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11797  rhs = consdata->rhs;
11798  }
11799  else
11800  {
11801  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11802  {
11803  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11804  lhs = consdata->lhs;
11805  }
11806  else
11807  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11808  }
11809  ++(*nchgsides);
11810 
11811  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11812  assert(!haslhs || !SCIPisNegative(scip, lhs));
11813 
11814  /* get new constraint data */
11815  nvars = consdata->nvars;
11816  assert(nvars >= 2);
11817 
11818  allcoefintegral = TRUE;
11819 
11820 #ifndef NDEBUG
11821  /* check integrality */
11822  for( w = offsetv + 1; w < nvars; ++w )
11823  {
11824  assert(SCIPisIntegral(scip, vals[w]));
11825  }
11826 #endif
11827  SCIPdebugPrintCons(scip, cons, NULL);
11828  }
11829 
11830  /* try to find a better gcd, when having large coefficients */
11831  if( offsetv >= 0 && gcd == 1 )
11832  {
11833  /* calculate greatest common divisor for all general variables */
11834  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11835 
11836  if( gcd > 1 )
11837  {
11838  gcd = -1;
11839  candpos = -1;
11840 
11841  for( v = nvars - 1; v > offsetv; --v )
11842  {
11843  assert(!SCIPisZero(scip, vals[v]));
11844  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11845  break;
11846 
11847  if( !SCIPisIntegral(scip, vals[v]) )
11848  {
11849  allcoefintegral = FALSE;
11850  break;
11851  }
11852 
11853  oldgcd = gcd;
11854 
11855  if( gcd == -1 )
11856  {
11857  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11858  assert(gcd >= 1);
11859  }
11860  else
11861  {
11862  /* calculate greatest common divisor for all general and binary variables */
11863  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11864  }
11865 
11866  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11867  * can stop searching
11868  */
11869  if( gcd == 1 )
11870  {
11871  if( !SCIPvarIsBinary(vars[v]) )
11872  break;
11873 
11874  /* found candidate */
11875  if( candpos == -1 )
11876  {
11877  gcd = oldgcd;
11878  candpos = v;
11879  }
11880  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11881  else
11882  break;
11883  }
11884  }
11885  assert(v > offsetv || candpos > offsetv);
11886  }
11887  else
11888  candpos = -1;
11889  }
11890  else
11891  candpos = nvars - 1;
11892 
11893  /* check last coefficient for integrality */
11894  if( gcd > 1 && allcoefintegral && !redundant )
11895  {
11896  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11897  allcoefintegral = FALSE;
11898  }
11899 
11900  /* check for further necessary coefficient adjustments */
11901  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11902  {
11903  assert(offsetv + 1 < nvars);
11904  assert(0 <= candpos && candpos < nvars);
11905 
11906  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
11907  {
11908  SCIP_Bool notchangable = FALSE;
11909 
11910 #ifndef NDEBUG
11911  /* check integrality */
11912  for( w = offsetv + 1; w < nvars; ++w )
11913  {
11914  assert(SCIPisIntegral(scip, vals[w]));
11915  }
11916 #endif
11917 
11918  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11919  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11920  {
11921  /* determine the remainder of the side and the gcd */
11922  if( hasrhs )
11923  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11924  else
11925  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11926  assert(rest >= 0);
11927  assert(rest < gcd);
11928 
11929  /* determine the remainder of the coefficient candidate and the gcd */
11930  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11931  assert(restcoef >= 1);
11932  assert(restcoef < gcd);
11933 
11934  if( hasrhs )
11935  {
11936  /* calculate new coefficient */
11937  if( restcoef > rest )
11938  newcoef = vals[candpos] - restcoef + gcd;
11939  else
11940  newcoef = vals[candpos] - restcoef;
11941  }
11942  else
11943  {
11944  /* calculate new coefficient */
11945  if( rest == 0 || restcoef < rest )
11946  newcoef = vals[candpos] - restcoef;
11947  else
11948  newcoef = vals[candpos] - restcoef + gcd;
11949  }
11950 
11951  /* done */
11952 
11953  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11954  * another with the big coefficient was set to 1
11955  */
11956  if( hasrhs && SCIPisZero(scip, newcoef) )
11957  {
11958  notchangable = TRUE;
11959  }
11960  else if( SCIPisZero(scip, newcoef) )
11961  {
11962  /* delete old redundant coefficient */
11963  SCIP_CALL( delCoefPos(scip, cons, candpos) );
11964  ++(*nchgcoefs);
11965  }
11966  else
11967  {
11968  /* replace old with new coefficient */
11969  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11970  ++(*nchgcoefs);
11971  }
11972  }
11973  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11974  {
11975  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11976  }
11977 
11978  /* correct side and big coefficients */
11979  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11980  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11981  {
11982  if( haslhs )
11983  {
11984  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11985 
11986  SCIP_CALL( chgLhs(scip, cons, newcoef) );
11987  ++(*nchgsides);
11988  }
11989  else
11990  {
11991  assert(hasrhs);
11992  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
11993 
11994  SCIP_CALL( chgRhs(scip, cons, newcoef) );
11995  ++(*nchgsides);
11996  }
11997 
11998  /* correct coefficients up front */
11999  for( w = offsetv; w >= 0; --w )
12000  {
12001  assert(vals[w] > 0);
12002 
12003  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12004  }
12005  (*nchgcoefs) += (offsetv + 1);
12006  }
12007 
12008  if( !notchangable )
12009  {
12010  /* normalize constraint */
12011  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12012  assert(vars == consdata->vars);
12013  assert(vals == consdata->vals);
12014 
12015  if( *infeasible )
12016  return SCIP_OKAY;
12017 
12018  /* get new constraint data */
12019  nvars = consdata->nvars;
12020  assert(nvars >= 2);
12021 
12022  SCIPdebugPrintCons(scip, cons, NULL);
12023 
12024  lhs = consdata->lhs;
12025  rhs = consdata->rhs;
12026  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12027  assert(!haslhs || !SCIPisNegative(scip, lhs));
12028  }
12029  }
12030  }
12031  }
12032 
12033  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12034  /* no continuous variables are left over */
12035  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12036  return SCIP_OKAY;
12037 
12038  onlybin = TRUE;
12039  allcoefintegral = TRUE;
12040  /* check if all variables are of binary type */
12041  for( v = nvars - 1; v >= 0; --v )
12042  {
12043  if( !SCIPvarIsBinary(vars[v]) )
12044  onlybin = FALSE;
12045  if( !SCIPisIntegral(scip, vals[v]) )
12046  allcoefintegral = FALSE;
12047  }
12048 
12049  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12050  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12051  *
12052  * @todo there are some steps missing ....
12053  */
12054  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12055  {
12056  SCIP_Real val;
12057  SCIP_Real newval;
12058  SCIP_Real frac = 0.0;
12059  SCIP_Bool found = FALSE;
12060 
12061  if( hasrhs )
12062  {
12063  if( allcoefintegral )
12064  {
12065  /* replace old with new right hand side */
12066  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12067  ++(*nchgsides);
12068  }
12069  else
12070  {
12071  siderest = rhs - SCIPfloor(scip, rhs);
12072 
12073  /* try to round down all non-integral coefficients */
12074  for( v = nvars - 1; v >= 0; --v )
12075  {
12076  val = vals[v];
12077 
12078  /* add up all possible fractional parts */
12079  if( !SCIPisIntegral(scip, val) )
12080  {
12081  lb = SCIPvarGetLbGlobal(vars[v]);
12082  ub = SCIPvarGetUbGlobal(vars[v]);
12083 
12084  /* at least one bound need to be at zero */
12085  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12086  return SCIP_OKAY;
12087 
12088  /* swap bounds for 'standard' form */
12089  if( !SCIPisFeasZero(scip, lb) )
12090  {
12091  ub = lb;
12092  val *= -1;
12093  }
12094 
12095  found = TRUE;
12096 
12097  frac += (val - SCIPfloor(scip, val)) * ub;
12098 
12099  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12100  *
12101  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12102  * x3, x4 set to 1 would be infeasible but feasible after flooring
12103  */
12104  if( SCIPisGT(scip, frac, siderest) )
12105  return SCIP_OKAY;
12106  }
12107  }
12108  assert(v == -1);
12109 
12110  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12111 
12112  /* round rhs and coefficients to integral values */
12113  if( found )
12114  {
12115  for( v = nvars - 1; v >= 0; --v )
12116  {
12117  val = vals[v];
12118 
12119  /* add the whole fractional part */
12120  if( !SCIPisIntegral(scip, val) )
12121  {
12122  lb = SCIPvarGetLbGlobal(vars[v]);
12123 
12124  if( SCIPisFeasZero(scip, lb) )
12125  newval = SCIPfloor(scip, val);
12126  else
12127  newval = SCIPceil(scip, val);
12128 
12129  if( SCIPisZero(scip, newval) )
12130  {
12131  /* delete old redundant coefficient */
12132  SCIP_CALL( delCoefPos(scip, cons, v) );
12133  ++(*nchgcoefs);
12134  }
12135  else
12136  {
12137  /* replace old with new coefficient */
12138  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12139  ++(*nchgcoefs);
12140  }
12141  }
12142  }
12143  }
12144 
12145  /* replace old with new right hand side */
12146  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12147  ++(*nchgsides);
12148  }
12149  }
12150  else
12151  {
12152  if( allcoefintegral )
12153  {
12154  /* replace old with new left hand side */
12155  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12156  ++(*nchgsides);
12157  }
12158  else
12159  {
12160  /* cannot floor left hand side to zero */
12161  if( SCIPisLT(scip, lhs, 1.0) )
12162  return SCIP_OKAY;
12163 
12164  siderest = lhs - SCIPfloor(scip, lhs);
12165 
12166  /* try to round down all non-integral coefficients */
12167  for( v = nvars - 1; v >= 0; --v )
12168  {
12169  val = vals[v];
12170 
12171  /* add up all possible fractional parts */
12172  if( !SCIPisIntegral(scip, val) )
12173  {
12174  lb = SCIPvarGetLbGlobal(vars[v]);
12175  ub = SCIPvarGetUbGlobal(vars[v]);
12176 
12177  /* at least one bound need to be at zero */
12178  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12179  return SCIP_OKAY;
12180 
12181  /* swap bounds for 'standard' form */
12182  if( !SCIPisFeasZero(scip, lb) )
12183  {
12184  ub = lb;
12185  val *= -1;
12186  }
12187 
12188  /* cannot floor to zero */
12189  if( SCIPisLT(scip, val, 1.0) )
12190  return SCIP_OKAY;
12191 
12192  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12193  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12194  return SCIP_OKAY;
12195 
12196  found = TRUE;
12197 
12198  frac += (val - SCIPfloor(scip, val)) * ub;
12199 
12200  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12201  * fractional parts of the variables, we cannot tighten the coefficients
12202  *
12203  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12204  * x2-x4 set to 1 would be feasible but not after flooring
12205  */
12206  if( SCIPisGE(scip, frac, 1 + siderest) )
12207  return SCIP_OKAY;
12208  }
12209  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12210  else
12211  return SCIP_OKAY;
12212  }
12213  assert(v == -1);
12214 
12215  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12216 
12217  /* round lhs and coefficients to integral values */
12218  if( found )
12219  {
12220  for( v = nvars - 1; v >= 0; --v )
12221  {
12222  val = vals[v];
12223 
12224  /* add the whole fractional part */
12225  if( !SCIPisIntegral(scip, val) )
12226  {
12227  lb = SCIPvarGetLbGlobal(vars[v]);
12228 
12229  if( SCIPisFeasZero(scip, lb) )
12230  newval = SCIPfloor(scip, val);
12231  else
12232  newval = SCIPceil(scip, val);
12233 
12234  if( SCIPisZero(scip, newval) )
12235  {
12236  /* delete old redundant coefficient */
12237  SCIP_CALL( delCoefPos(scip, cons, v) );
12238  ++(*nchgcoefs);
12239  }
12240  else
12241  {
12242  /* replace old with new coefficient */
12243  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12244  ++(*nchgcoefs);
12245  }
12246  }
12247  }
12248  }
12249 
12250  /* replace old with new left hand side */
12251  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12252  ++(*nchgsides);
12253  }
12254  }
12255 
12256  /* normalize constraint */
12257  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12258  assert(vars == consdata->vars);
12259  assert(vals == consdata->vals);
12260 
12261  if( *infeasible )
12262  return SCIP_OKAY;
12263 
12264  rhs = consdata->rhs;
12265  lhs = consdata->lhs;
12266 
12267  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12268  assert(!haslhs || !SCIPisNegative(scip, lhs));
12269 
12270  SCIPdebugPrintCons(scip, cons, NULL);
12271 
12272  nvars = consdata->nvars;
12273  if( nvars < 2 )
12274  return SCIP_OKAY;
12275 
12276  allcoefintegral = TRUE;
12277 #ifndef NDEBUG
12278  /* debug check if all coefficients are really integral */
12279  for( v = nvars - 1; v >= 0; --v )
12280  assert(SCIPisIntegral(scip, vals[v]));
12281 #endif
12282  }
12283 
12284  /* @todo following can also work on non integral coefficients, need more investigation */
12285  /* only check constraints with integral coefficients on all integral variables */
12286  if( !allcoefintegral )
12287  return SCIP_OKAY;
12288 
12289  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12290  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12291  return SCIP_OKAY;
12292 
12293  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12294  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12295  return SCIP_OKAY;
12296 
12297  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12298  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12299  return SCIP_OKAY;
12300 
12301  assert(nvars >= 2);
12302 
12303  /* start gcd procedure for all variables */
12304  do
12305  {
12306  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12307  SCIPdebug( oldnchgsides = *nchgsides; )
12308 
12309  /* stop if we have two coeffcients which are one in absolute value */
12310  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12311  return SCIP_OKAY;
12312 
12313  gcd = -1;
12314 
12315  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12316  * because coefficients of non-binary variables might have changed to zero */
12317  if( !onlybin )
12318  {
12319  foundbin = -1;
12320  onlybin = TRUE;
12321 
12322  for( v = nvars - 1; v >= 0; --v )
12323  {
12324  assert(!SCIPisZero(scip, vals[v]));
12325  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12326 
12327  if( SCIPvarIsBinary(vars[v]) )
12328  {
12329  if( foundbin == -1 )
12330  foundbin = v;
12331  continue;
12332  }
12333  else
12334  onlybin = FALSE;
12335 
12336  absval = REALABS(vals[v]);
12337  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12338  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12339  */
12340  assert(SCIPisFeasIntegral(scip, absval));
12341 
12342  if( gcd == -1 )
12343  {
12344  gcd = (SCIP_Longint)(absval + feastol);
12345  assert(gcd >= 1);
12346  }
12347  else
12348  {
12349  /* calculate greatest common divisor for all general variables */
12350  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12351  }
12352  if( gcd == 1 )
12353  break;
12354  }
12355  }
12356  else
12357  foundbin = nvars - 1;
12358 
12359  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12360  if( gcd == 1 || foundbin == -1)
12361  return SCIP_OKAY;
12362 
12363  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12364 
12365  candpos = -1;
12366  candpos2 = -1;
12367 
12368  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12369  * change the coefficient
12370  */
12371  for( v = foundbin; v >= 0; --v )
12372  {
12373  if( onlybin || SCIPvarIsBinary(vars[v]) )
12374  {
12375  absval = REALABS(vals[v]);
12376  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12377  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12378  */
12379  assert(SCIPisFeasIntegral(scip, absval));
12380 
12381  oldgcd = gcd;
12382 
12383  if( gcd == -1 )
12384  {
12385  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12386  assert(gcd >= 1);
12387  }
12388  else
12389  {
12390  /* calculate greatest common divisor for all general and binary variables */
12391  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12392  }
12393 
12394  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12395  * can terminate
12396  */
12397  if( gcd == 1 )
12398  {
12399  /* found candidate */
12400  if( candpos == -1 )
12401  {
12402  gcd = oldgcd;
12403  candpos = v;
12404 
12405  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12406  * the coefficient change
12407  */
12408  if( onlybin && v == foundbin - 1 )
12409  candpos2 = foundbin;
12410  }
12411  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12412  else
12413  {
12414  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12415  {
12416  assert(candpos2 == nvars - 1);
12417 
12418  /* take new candidates */
12419  candpos = candpos2;
12420 
12421  /* recalculate gcd from scratch */
12422  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12423  assert(gcd >= 1);
12424 
12425  /* calculate greatest common divisor for all general and binary variables */
12426  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12427  if( gcd == 1 )
12428  return SCIP_OKAY;
12429  }
12430  else
12431  /* cannot determine a possible coefficient for reduction */
12432  return SCIP_OKAY;
12433  }
12434  }
12435  }
12436  }
12437  assert(gcd >= 2);
12438 
12439  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12440  * further
12441  */
12442  assert(candpos >= 0 && candpos < nvars);
12443 
12444  /* all variables and all coefficients are integral, so the side should be too */
12445  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12446 
12447  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12448  * @see normalizeCons()
12449  */
12450  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12451  assert(!haslhs || !SCIPisNegative(scip, lhs));
12452 
12453  /* determine the remainder of the side and the gcd */
12454  if( hasrhs )
12455  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12456  else
12457  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12458  assert(rest >= 0);
12459  assert(rest < gcd);
12460 
12461  /* determine the remainder of the coefficient candidate and the gcd */
12462  if( vals[candpos] < 0 )
12463  {
12464  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12465  assert(restcoef <= -1);
12466  restcoef += gcd;
12467  }
12468  else
12469  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12470  assert(restcoef >= 1);
12471  assert(restcoef < gcd);
12472 
12473  if( hasrhs )
12474  {
12475  if( rest > 0 )
12476  {
12477  /* replace old with new right hand side */
12478  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12479  ++(*nchgsides);
12480  }
12481 
12482  /* calculate new coefficient */
12483  if( restcoef > rest )
12484  newcoef = vals[candpos] - restcoef + gcd;
12485  else
12486  newcoef = vals[candpos] - restcoef;
12487  }
12488  else
12489  {
12490  if( rest > 0 )
12491  {
12492  /* replace old with new left hand side */
12493  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12494  ++(*nchgsides);
12495  }
12496 
12497  /* calculate new coefficient */
12498  if( rest == 0 || restcoef < rest )
12499  newcoef = vals[candpos] - restcoef;
12500  else
12501  newcoef = vals[candpos] - restcoef + gcd;
12502  }
12503  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12504 
12505  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));
12506 
12507  if( SCIPisZero(scip, newcoef) )
12508  {
12509  /* delete redundant coefficient */
12510  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12511  }
12512  else
12513  {
12514  /* replace old with new coefficient */
12515  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12516  }
12517  ++(*nchgcoefs);
12518 
12519  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12520  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12521  assert(vars == consdata->vars);
12522  assert(vals == consdata->vals);
12523 
12524  if( *infeasible )
12525  return SCIP_OKAY;
12526 
12527  SCIPdebugPrintCons(scip, cons, NULL);
12528 
12529  rhs = consdata->rhs;
12530  lhs = consdata->lhs;
12531  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12532  assert(!haslhs || !SCIPisNegative(scip, lhs));
12533 
12534  nvars = consdata->nvars;
12535 
12536  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));
12537  }
12538  while( nvars >= 2 );
12539 
12540  return SCIP_OKAY;
12541 }
12542 
12543 
12544 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12545  * cons0 := a * cons0 + b * cons1,
12546  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12547  * for numerical stability, we will only accept integral a and b;
12548  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12549  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12550  */
12551 static
12553  SCIP* scip, /**< SCIP data structure */
12554  SCIP_CONS* cons0, /**< (in)equality to modify */
12555  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12556  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12557  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12558  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12559  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12560  int nvarscommon, /**< number of variables, that appear in both constraints */
12561  int commonidxweight, /**< variable weight sum of common variables */
12562  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12563  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12564  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12565  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12566  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12567  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12568  )
12570  SCIP_CONSDATA* consdata0;
12571  SCIP_CONSDATA* consdata1;
12572  SCIP_Real a;
12573  SCIP_Real b;
12574  SCIP_Real aggrcoef;
12575  SCIP_Real scalarsum;
12576  SCIP_Real bestscalarsum;
12577  SCIP_Bool betterscalarsum;
12578  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12579  int varweight;
12580  int nvars;
12581  int bestvarweight;
12582  int bestnvars;
12583  int bestv;
12584  int v;
12585  int i;
12586 
12587  assert(scip != NULL);
12588  assert(cons0 != NULL);
12589  assert(cons1 != NULL);
12590  assert(commonidx0 != NULL);
12591  assert(commonidx1 != NULL);
12592  assert(diffidx0minus1 != NULL);
12593  assert(diffidx1minus0 != NULL);
12594  assert(nvarscommon >= 1);
12595  assert(commonidxweight >= nvarscommon);
12596  assert(nchgcoefs != NULL);
12597  assert(aggregated != NULL);
12598 
12599  assert(SCIPconsIsActive(cons0));
12600  assert(SCIPconsIsActive(cons1));
12601 
12602  *infeasible = FALSE;
12603 
12604  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12605 
12606  /* cons0 is an (in)equality */
12607  consdata0 = SCIPconsGetData(cons0);
12608  assert(consdata0 != NULL);
12609  assert(consdata0->nvars >= 1);
12610  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12611  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12612 
12613  /* cons1 is an equality */
12614  consdata1 = SCIPconsGetData(cons1);
12615  assert(consdata1 != NULL);
12616  assert(consdata1->nvars >= 1);
12617  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12618  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12619 
12620  *aggregated = FALSE;
12621 
12622  /* search for the best common variable such that
12623  * val1[var] * consdata0 - val0[var] * consdata1
12624  * has least weighted number of variables
12625  */
12626  bestvarweight = commonidxweight + diffidx0minus1weight;
12627  bestnvars = consdata0->nvars;
12628  bestv = -1;
12629  bestscalarsum = 0.0;
12630  commonvarlindependent = TRUE;
12631  for( v = 0; v < nvarscommon; ++v )
12632  {
12633  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12634  a = consdata1->vals[commonidx1[v]];
12635  b = -consdata0->vals[commonidx0[v]];
12636 
12637  /* only try aggregation, if coefficients are integral (numerical stability) */
12638  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12639  {
12640  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12641  varweight = diffidx0minus1weight + diffidx1minus0weight;
12642  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12643  scalarsum = REALABS(a) + REALABS(b);
12644  betterscalarsum = (scalarsum < bestscalarsum);
12645  for( i = 0; i < nvarscommon
12646  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12647  {
12648  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12649  if( !SCIPisZero(scip, aggrcoef) )
12650  {
12651  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12652  nvars++;
12653  }
12654  }
12655  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12656  {
12657  bestv = v;
12658  bestvarweight = varweight;
12659  bestnvars = nvars;
12660  bestscalarsum = scalarsum;
12661  }
12662  }
12663 
12664  /* update commonvarlindependent flag, if still TRUE:
12665  * 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
12666  */
12667  if( commonvarlindependent && v > 0 )
12668  commonvarlindependent = SCIPisEQ(scip,
12669  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12670  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12671  }
12672 
12673  /* if better aggregation was found, create new constraint and delete old one */
12674  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12675  {
12676  SCIP_CONS* newcons;
12677  SCIP_CONSDATA* newconsdata;
12678  SCIP_VAR** newvars;
12679  SCIP_Real* newvals;
12680  SCIP_Real newlhs;
12681  SCIP_Real newrhs;
12682  int newnvars;
12683 
12684  if( bestv != -1 )
12685  {
12686  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12687  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12688  {
12689  a = consdata1->vals[commonidx1[bestv]];
12690  b = -consdata0->vals[commonidx0[bestv]];
12691  }
12692  else
12693  {
12694  a = -consdata1->vals[commonidx1[bestv]];
12695  b = consdata0->vals[commonidx0[bestv]];
12696  }
12697  assert(SCIPisIntegral(scip, a));
12698  assert(SCIPisPositive(scip, a));
12699  assert(SCIPisIntegral(scip, b));
12700  assert(!SCIPisZero(scip, b));
12701  }
12702  else
12703  {
12704  assert(commonvarlindependent);
12705  if( consdata1->vals[commonidx1[0]] > 0.0 )
12706  {
12707  a = consdata1->vals[commonidx1[0]];
12708  b = -consdata0->vals[commonidx0[0]];
12709  }
12710  else
12711  {
12712  a = -consdata1->vals[commonidx1[0]];
12713  b = consdata0->vals[commonidx0[0]];
12714  }
12715  assert(SCIPisPositive(scip, a));
12716  assert(!SCIPisZero(scip, b));
12717 
12718  /* if a/b is integral, then we can easily choose integer multipliers */
12719  if( SCIPisIntegral(scip, a/b) )
12720  {
12721  if( a/b > 0 )
12722  {
12723  a /= b;
12724  b = 1.0;
12725  }
12726  else
12727  {
12728  a /= -b;
12729  b = -1.0;
12730  }
12731  }
12732 
12733  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12734  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12735  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12736  }
12737 
12738  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12739  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12740  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12741  SCIPdebugPrintCons(scip, cons0, NULL);
12742  SCIPdebugPrintCons(scip, cons1, NULL);
12743 
12744  /* get temporary memory for creating the new linear constraint */
12745  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12746  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12747 
12748  /* calculate the common coefficients, if we have not recognized linear dependency */
12749  newnvars = 0;
12750  if( !commonvarlindependent )
12751  {
12752  for( i = 0; i < nvarscommon; ++i )
12753  {
12754  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12755  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12756 
12757  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12758  if( !SCIPisZero(scip, aggrcoef) )
12759  {
12760  assert(newnvars < bestnvars);
12761  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12762  newvals[newnvars] = aggrcoef;
12763  newnvars++;
12764  }
12765  }
12766  }
12767  else
12768  {
12769  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12770 #ifndef NDEBUG
12771  for( i = 0; i < nvarscommon; ++i )
12772  {
12773  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12774  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12775 
12776  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12777  assert(SCIPisZero(scip, aggrcoef));
12778  }
12779 #endif
12780  }
12781 
12782  /* calculate the coefficients appearing in cons0 but not in cons1 */
12783  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12784  {
12785  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12786 
12787  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12788  assert(!SCIPisZero(scip, aggrcoef));
12789  assert(newnvars < bestnvars);
12790  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12791  newvals[newnvars] = aggrcoef;
12792  newnvars++;
12793  }
12794 
12795  /* calculate the coefficients appearing in cons1 but not in cons0 */
12796  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12797  {
12798  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12799 
12800  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12801  assert(!SCIPisZero(scip, aggrcoef));
12802  assert(newnvars < bestnvars);
12803  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12804  newvals[newnvars] = aggrcoef;
12805  newnvars++;
12806  }
12807  assert(newnvars == bestnvars);
12808 
12809  /* calculate the new left and right hand side of the (in)equality */
12810  assert(!SCIPisInfinity(scip, -consdata1->lhs));
12811  assert(!SCIPisInfinity(scip, consdata1->rhs));
12812  if( SCIPisInfinity(scip, -consdata0->lhs) )
12813  newlhs = -SCIPinfinity(scip);
12814  else
12815  newlhs = a * consdata0->lhs + b * consdata1->lhs;
12816  if( SCIPisInfinity(scip, consdata0->rhs) )
12817  newrhs = SCIPinfinity(scip);
12818  else
12819  newrhs = a * consdata0->rhs + b * consdata1->rhs;
12820 
12821  /* create the new linear constraint */
12822  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12824  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12825  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12827 
12828  newconsdata = SCIPconsGetData(newcons);
12829  assert(newconsdata != NULL);
12830 
12831  /* copy the upgraded flag from the old cons0 to the new constraint */
12832  newconsdata->upgraded = consdata0->upgraded;
12833 
12834  /* normalize the new constraint */
12835  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12836 
12837  if( *infeasible )
12838  goto TERMINATE;
12839 
12840  /* check, if we really want to use the new constraint instead of the old one:
12841  * use the new one, if the maximum norm doesn't grow too much
12842  */
12843  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12844  {
12845  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12846  SCIPdebugPrintCons(scip, newcons, NULL);
12847 
12848  /* update the statistics: we changed all coefficients */
12849  if( !consdata0->upgraded )
12850  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12851  *aggregated = TRUE;
12852 
12853  /* delete the old constraint, and add the new linear constraint to the problem */
12854  SCIP_CALL( SCIPdelCons(scip, cons0) );
12855  SCIP_CALL( SCIPaddCons(scip, newcons) );
12856  }
12857 
12858  TERMINATE:
12859  /* release the new constraint */
12860  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12861 
12862  /* free temporary memory */
12863  SCIPfreeBufferArray(scip, &newvals);
12864  SCIPfreeBufferArray(scip, &newvars);
12865  }
12866 
12867  return SCIP_OKAY;
12868 }
12869 
12870 /** gets the key of the given element */
12871 static
12872 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12873 { /*lint --e{715}*/
12874  /* the key is the element itself */
12875  return elem;
12876 }
12877 
12878 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12879  * coefficients are either equal or negated
12880  */
12881 static
12882 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12883 {
12884  SCIP* scip;
12885  SCIP_CONSDATA* consdata1;
12886  SCIP_CONSDATA* consdata2;
12887  SCIP_Real cons1scale;
12888  SCIP_Real cons2scale;
12889  int i;
12890 
12891  assert(key1 != NULL);
12892  assert(key2 != NULL);
12893  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12894  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12895  assert(consdata1->sorted);
12896  assert(consdata2->sorted);
12897 
12898  scip = (SCIP*)userptr;
12899  assert(scip != NULL);
12900 
12901  /* if it is the same constraint we dont need to check anything */
12902  if( key1 == key2 )
12903  return TRUE;
12904 
12905  /* checks trivial case */
12906  if( consdata1->nvars != consdata2->nvars )
12907  return FALSE;
12908 
12909  /* tests if variables are equal */
12910  for( i = 0; i < consdata1->nvars; ++i )
12911  {
12912  if( consdata1->vars[i] != consdata2->vars[i] )
12913  {
12914  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12915  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12916  return FALSE;
12917  }
12918  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12919  }
12920 
12921  /* compute scale before comparing coefficients of constraints */
12922  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
12923  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
12924 
12925  /* tests if coefficients are equal with the computed scale */
12926  for( i = 0; i < consdata1->nvars; ++i )
12927  {
12928  SCIP_Real val1;
12929  SCIP_Real val2;
12930 
12931  val1 = consdata1->vals[i] * cons1scale;
12932  val2 = consdata2->vals[i] * cons2scale;
12933 
12934  if( !SCIPisEQ(scip, val1, val2) )
12935  return FALSE;
12936  }
12937 
12938  return TRUE;
12939 }
12940 
12941 /** returns the hash value of the key */
12942 static
12943 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12944 {
12945  SCIP_CONSDATA* consdata;
12946  int minidx;
12947  int mididx;
12948  int maxidx;
12949  SCIP_Real scale;
12950 #ifndef NDEBUG
12951  SCIP* scip;
12952 
12953  scip = (SCIP*)userptr;
12954  assert(scip != NULL);
12955 #endif
12956 
12957  assert(key != NULL);
12958  consdata = SCIPconsGetData((SCIP_CONS*)key);
12959  assert(consdata != NULL);
12960  assert(consdata->nvars > 0);
12961 
12962  assert(consdata->sorted);
12963 
12964  minidx = SCIPvarGetIndex(consdata->vars[0]);
12965  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12966  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12967  assert(minidx >= 0 && minidx <= maxidx);
12968  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
12969 
12970  /* using only the variable indices as hash, since the values are compared by epsilon */
12971  return SCIPhashFour(consdata->nvars,
12972  SCIPcombineTwoInt(minidx, SCIPrealHashCode(consdata->vals[0] * scale)),
12973  SCIPcombineTwoInt(mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale)),
12974  SCIPcombineTwoInt(maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale))); /*lint !e571*/
12975 }
12976 
12977 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
12978  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
12979  */
12980 static
12981 unsigned int getParallelConsKey(
12982  SCIP_CONS* cons /**< linear constraint */
12983  )
12984 {
12985  SCIP_CONSDATA* consdata;
12986 
12987  assert(cons != NULL);
12988 
12989  consdata = SCIPconsGetData(cons);
12990  assert(consdata != NULL);
12991 
12992  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
12993 }
12994 
12995 /** updates the hashtable such that out of all constraints in the hashtable that are detected
12996  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
12997  * and all others are removed from the hashtable and stored in the given array
12998  */
12999 static
13001  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13002  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13003  * upon return will contain the constraint that should be kept */
13004  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13005  * these constraints where removed from the hashtable */
13006  int* nparallelconss /**< pointer to return number of parallel constraints */
13007  )
13008 {
13009  SCIP_CONS* parallelcons;
13010  unsigned int querykey;
13011 
13012  *nparallelconss = 0;
13013  querykey = getParallelConsKey(*querycons);
13014 
13015  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13016  {
13017  unsigned int conskey = getParallelConsKey(parallelcons);
13018 
13019  if( conskey < querykey )
13020  {
13021  parallelconss[(*nparallelconss)++] = *querycons;
13022  *querycons = parallelcons;
13023  querykey = conskey;
13024  }
13025  else
13026  {
13027  parallelconss[(*nparallelconss)++] = parallelcons;
13028  }
13029 
13030  /* if the constraint that just came out of the hash table is the one that is kept,
13031  * we do not need to look into the hashtable again, since the invariant is that
13032  * in the hashtable only pair-wise non-parallel constraints are contained.
13033  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13034  * could be contained due to non-transitivity of the equality comparison.
13035  * Also we can return immediately, since parallelcons is already contained in the
13036  * hashtable and we do not need to remove and reinsert it.
13037  */
13038  if( *querycons == parallelcons )
13039  return SCIP_OKAY;
13040 
13041  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13042  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13043  }
13044 
13045  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13046  * comnpares equal to querycons at this point
13047  */
13048 #ifndef NDEBUG
13049  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13050 #else
13051  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13052 #endif
13053 
13054  return SCIP_OKAY;
13055 }
13056 
13057 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13058  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13059  */
13060 static
13062  SCIP* scip, /**< SCIP data structure */
13063  BMS_BLKMEM* blkmem, /**< block memory */
13064  SCIP_CONS** conss, /**< constraint set */
13065  int nconss, /**< number of constraints in constraint set */
13066  int* firstchange, /**< pointer to store first changed constraint */
13067  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13068  int* ndelconss, /**< pointer to count number of deleted constraints */
13069  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13070  )
13071 {
13072  SCIP_HASHTABLE* hashtable;
13073  SCIP_CONS** parallelconss;
13074  int nparallelconss;
13075  int hashtablesize;
13076  int c;
13077 
13078  assert(scip != NULL);
13079  assert(blkmem != NULL);
13080  assert(conss != NULL);
13081  assert(firstchange != NULL);
13082  assert(cutoff != NULL);
13083  assert(ndelconss != NULL);
13084  assert(nchgsides != NULL);
13085 
13086  /* create a hash table for the constraint set */
13087  hashtablesize = nconss;
13088  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13089  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13090 
13091  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13092 
13093  /* check all constraints in the given set for redundancy */
13094  for( c = 0; c < nconss; ++c )
13095  {
13096  SCIP_CONS* cons0;
13097  SCIP_CONSDATA* consdata0;
13098 
13099  cons0 = conss[c];
13100 
13101  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13102  continue;
13103 
13104  /* check for interuption */
13105  if( c % 1000 == 0 && SCIPisStopped(scip) )
13106  break;
13107 
13108  /* sorts the constraint */
13109  consdata0 = SCIPconsGetData(cons0);
13110  assert(consdata0 != NULL);
13111  SCIP_CALL( consdataSort(scip, consdata0) );
13112  assert(consdata0->sorted);
13113 
13114  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13115  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13116  * first variable is positive
13117  * Also inserts cons0 into the hashtable.
13118  */
13119  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13120 
13121  if( nparallelconss != 0 )
13122  {
13123  SCIP_Real lhs;
13124  SCIP_Real rhs;
13125 
13126  int i;
13127 
13128  /* cons0 may have been changed in retrieveParallelConstraints() */
13129  consdata0 = SCIPconsGetData(cons0);
13130 
13131  lhs = consdata0->lhs;
13132  rhs = consdata0->rhs;
13133 
13134  for( i = 0; i < nparallelconss; ++i )
13135  {
13136  SCIP_CONS* consdel;
13137  SCIP_CONSDATA* consdatadel;
13138  SCIP_Real scale;
13139 
13140  consdel = parallelconss[i];
13141  consdatadel = SCIPconsGetData(consdel);
13142 
13143  assert(SCIPconsIsActive(consdel));
13144  assert(!SCIPconsIsModifiable(consdel));
13145 
13146  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13147  * delete old constraints afterwards
13148  */
13149  assert(consdatadel != NULL);
13150  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13151 
13152  assert(consdatadel->sorted);
13153  assert(consdata0->vars[0] == consdatadel->vars[0]);
13154 
13155  scale = consdata0->vals[0] / consdatadel->vals[0];
13156  assert(scale != 0.0);
13157 
13158  /* in debug mode, check that all coefficients are equal with respect to epsilon
13159  * if the constraints are in equilibrium scale
13160  */
13161 #ifndef NDEBUG
13162  {
13163  int k;
13164  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13165  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13166 
13167  for( k = 0; k < consdata0->nvars; ++k )
13168  {
13169  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13170  }
13171  }
13172 #endif
13173 
13174  if( scale > 0.0 )
13175  {
13176  /* the coefficients of both constraints are parallel with a positive scale */
13177  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13178  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13179  SCIPdebugPrintCons(scip, cons0, NULL);
13180  SCIPdebugPrintCons(scip, consdel, NULL);
13181 
13182  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13183  lhs = MAX(scale * consdatadel->lhs, lhs);
13184 
13185  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13186  rhs = MIN(scale * consdatadel->rhs, rhs);
13187  }
13188  else
13189  {
13190  /* the coefficients of both rows are negations */
13191  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13192  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13193  SCIPdebugPrintCons(scip, cons0, NULL);
13194  SCIPdebugPrintCons(scip, consdel, NULL);
13195 
13196  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13197  lhs = MAX(scale * consdatadel->rhs, lhs);
13198 
13199  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13200  rhs = MIN(scale * consdatadel->lhs, rhs);
13201  }
13202 
13203  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13204  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13205 
13206  /* delete consdel */
13207  assert( ! consdata0->upgraded || consdatadel->upgraded );
13208  SCIP_CALL( SCIPdelCons(scip, consdel) );
13209  if( !consdatadel->upgraded )
13210  (*ndelconss)++;
13211  }
13212 
13213  if( SCIPisFeasLT(scip, rhs, lhs) )
13214  {
13215  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13216  *cutoff = TRUE;
13217  break;
13218  }
13219 
13220  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13221  if( lhs > rhs )
13222  {
13223  rhs = (lhs + rhs)/2;
13224  lhs = rhs;
13225  }
13226 
13227  /* update lhs and rhs of cons0 */
13228  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13229  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13230 
13231  /* update the first changed constraint to begin the next aggregation round with */
13232  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13233  *firstchange = SCIPconsGetPos(cons0);
13234 
13235  assert(SCIPconsIsActive(cons0));
13236  }
13237  }
13238 #ifdef SCIP_MORE_DEBUG
13239  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13241 #endif
13242 
13243  SCIPfreeBufferArray(scip, &parallelconss);
13244 
13245  /* free hash table */
13246  SCIPhashtableFree(&hashtable);
13247 
13248  return SCIP_OKAY;
13249 }
13250 
13251 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13252  * and removes or changes constraint accordingly
13253  */
13254 static
13256  SCIP* scip, /**< SCIP data structure */
13257  SCIP_CONS** conss, /**< constraint set */
13258  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13259  int chkind, /**< index of constraint to check against all prior indices upto startind */
13260  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13261  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13262  int* ndelconss, /**< pointer to count number of deleted constraints */
13263  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13264  int* nchgcoefs /**< pointer to count number of changed coefficients */
13265  )
13266 {
13267  SCIP_CONS* cons0;
13268  SCIP_CONSDATA* consdata0;
13269  int* commonidx0;
13270  int* commonidx1;
13271  int* diffidx0minus1;
13272  int* diffidx1minus0;
13273  uint64_t possignature0;
13274  uint64_t negsignature0;
13275  SCIP_Bool cons0changed;
13276  SCIP_Bool cons0isequality;
13277  int diffidx1minus0size;
13278  int c;
13279  SCIP_Real cons0lhs;
13280  SCIP_Real cons0rhs;
13281  SCIP_Bool cons0upgraded;
13282 
13283  assert(scip != NULL);
13284  assert(conss != NULL);
13285  assert(firstchange <= chkind);
13286  assert(cutoff != NULL);
13287  assert(ndelconss != NULL);
13288  assert(nchgsides != NULL);
13289  assert(nchgcoefs != NULL);
13290 
13291  /* get the constraint to be checked against all prior constraints */
13292  cons0 = conss[chkind];
13293  assert(cons0 != NULL);
13294  assert(SCIPconsIsActive(cons0));
13295  assert(!SCIPconsIsModifiable(cons0));
13296 
13297  consdata0 = SCIPconsGetData(cons0);
13298  assert(consdata0 != NULL);
13299  assert(consdata0->nvars >= 1);
13300  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13301 
13302  /* sort the constraint */
13303  SCIP_CALL( consdataSort(scip, consdata0) );
13304 
13305  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13306  consdataCalcSignatures(consdata0);
13307  possignature0 = consdata0->possignature;
13308  negsignature0 = consdata0->negsignature;
13309 
13310  /* get temporary memory for indices of common variables */
13311  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13312  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13313  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13314  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13315  diffidx1minus0size = consdata0->nvars;
13316 
13317  cons0lhs = consdata0->lhs;
13318  cons0rhs = consdata0->rhs;
13319  cons0upgraded = consdata0->upgraded;
13320 
13321  /* check constraint against all prior constraints */
13322  cons0changed = consdata0->changed;
13323  consdata0->changed = FALSE;
13324  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13325  {
13326  SCIP_CONS* cons1;
13327  SCIP_CONSDATA* consdata1;
13328  uint64_t possignature1;
13329  uint64_t negsignature1;
13330  SCIP_Bool cons0dominateslhs;
13331  SCIP_Bool cons1dominateslhs;
13332  SCIP_Bool cons0dominatesrhs;
13333  SCIP_Bool cons1dominatesrhs;
13334  SCIP_Bool cons1isequality;
13335  SCIP_Bool coefsequal;
13336  SCIP_Bool coefsnegated;
13337  SCIP_Bool tryaggregation;
13338  int nvarscommon;
13339  int nvars0minus1;
13340  int nvars1minus0;
13341  int commonidxweight;
13342  int diffidx0minus1weight;
13343  int diffidx1minus0weight;
13344  int v0;
13345  int v1;
13346 
13347  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13348  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13349  assert(cons0upgraded == consdata0->upgraded);
13350 
13351  cons1 = conss[c];
13352 
13353  /* cons1 has become inactive during presolving of constraint pairs */
13354  if( cons1 == NULL )
13355  continue;
13356 
13357  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13358  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13359 
13360  consdata1 = SCIPconsGetData(cons1);
13361  assert(consdata1 != NULL);
13362 
13363  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13364  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13365  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13366 
13367  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13368  if( !cons0changed && !consdata1->changed )
13369  continue;
13370 
13371  /* if both constraints are already upgraded, skip the pair;
13372  * because changes on these constraints cannot be applied to the instance anymore */
13373  if( cons0upgraded && consdata1->upgraded )
13374  continue;
13375 
13376  assert(consdata1->nvars >= 1);
13377 
13378  /* sort the constraint */
13379  SCIP_CALL( consdataSort(scip, consdata1) );
13380 
13381  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13382  consdataCalcSignatures(consdata1);
13383  possignature1 = consdata1->possignature;
13384  negsignature1 = consdata1->negsignature;
13385 
13386  /* the signatures give a quick test to check for domination and equality of coefficients */
13387  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13388  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13389  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13390  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13391  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13392  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13393  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13394  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13395  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13396  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13397  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13398  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13399  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13400  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13401  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13402  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13403  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13404  && !coefsequal && !coefsnegated && !tryaggregation )
13405  continue;
13406 
13407  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13408  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13409  {
13410  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13411  diffidx1minus0size = consdata1->nvars;
13412  }
13413 
13414  /* check consdata0 against consdata1:
13415  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13416  * consdata0 dominates consdata1 w.r.t. left hand side
13417  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13418  * consdata0 dominates consdata1 w.r.t. right hand side
13419  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13420  * ranged row (or equality)
13421  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13422  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13423  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13424  * number of continuous and integer variables are preferred:
13425  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13426  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13427  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13428  * to be positive to not switch the sense of the (in)equality cons0
13429  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13430  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13431  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13432  * to be positive to not switch the sense of the (in)equality cons1
13433  */
13434 
13435  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13436  nvarscommon = 0;
13437  commonidxweight = 0;
13438  nvars0minus1 = 0;
13439  diffidx0minus1weight = 0;
13440  nvars1minus0 = 0;
13441  diffidx1minus0weight = 0;
13442  v0 = 0;
13443  v1 = 0;
13444  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13445  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13446  || coefsequal || coefsnegated || tryaggregation) )
13447  {
13448  SCIP_VAR* var;
13449  SCIP_Real val0;
13450  SCIP_Real val1;
13451  int varcmp;
13452 
13453  /* test, if variable appears in only one or in both constraints */
13454  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13455  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13456  else if( v0 < consdata0->nvars )
13457  varcmp = -1;
13458  else
13459  varcmp = +1;
13460 
13461  switch( varcmp )
13462  {
13463  case -1:
13464  /* variable doesn't appear in consdata1 */
13465  var = consdata0->vars[v0];
13466  val0 = consdata0->vals[v0];
13467  val1 = 0.0;
13468  if( tryaggregation )
13469  {
13470  diffidx0minus1[nvars0minus1] = v0;
13471  nvars0minus1++;
13472  diffidx0minus1weight += getVarWeight(var);
13473  }
13474  v0++;
13475  coefsequal = FALSE;
13476  coefsnegated = FALSE;
13477  break;
13478 
13479  case +1:
13480  /* variable doesn't appear in consdata0 */
13481  var = consdata1->vars[v1];
13482  val0 = 0.0;
13483  val1 = consdata1->vals[v1];
13484  if( tryaggregation )
13485  {
13486  diffidx1minus0[nvars1minus0] = v1;
13487  nvars1minus0++;
13488  diffidx1minus0weight += getVarWeight(var);
13489  }
13490  v1++;
13491  coefsequal = FALSE;
13492  coefsnegated = FALSE;
13493  break;
13494 
13495  case 0:
13496  /* variable appears in both constraints */
13497  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13498  var = consdata0->vars[v0];
13499  val0 = consdata0->vals[v0];
13500  val1 = consdata1->vals[v1];
13501  if( tryaggregation )
13502  {
13503  commonidx0[nvarscommon] = v0;
13504  commonidx1[nvarscommon] = v1;
13505  nvarscommon++;
13506  commonidxweight += getVarWeight(var);
13507  }
13508  v0++;
13509  v1++;
13510  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13511  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13512  break;
13513 
13514  default:
13515  SCIPerrorMessage("invalid comparison result\n");
13516  SCIPABORT();
13517  var = NULL;
13518  val0 = 0.0;
13519  val1 = 0.0;
13520  }
13521  assert(var != NULL);
13522 
13523  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13524  if( SCIPisGT(scip, val0, val1) )
13525  {
13526  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13527  {
13528  cons0dominatesrhs = FALSE;
13529  cons1dominateslhs = FALSE;
13530  }
13531  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13532  {
13533  cons0dominateslhs = FALSE;
13534  cons1dominatesrhs = FALSE;
13535  }
13536  }
13537  else if( SCIPisLT(scip, val0, val1) )
13538  {
13539  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13540  {
13541  cons0dominateslhs = FALSE;
13542  cons1dominatesrhs = FALSE;
13543  }
13544  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13545  {
13546  cons0dominatesrhs = FALSE;
13547  cons1dominateslhs = FALSE;
13548  }
13549  }
13550  }
13551 
13552  /* check for disaggregated ranged rows */
13553  if( coefsequal || coefsnegated )
13554  {
13555  SCIP_CONS* consstay;
13556  SCIP_CONS* consdel;
13557 #ifndef NDEBUG
13558  SCIP_CONSDATA* consdatastay;
13559 #endif
13560  SCIP_CONSDATA* consdatadel;
13561  SCIP_Real lhs;
13562  SCIP_Real rhs;
13563  int consinddel;
13564 
13565  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13566  * best left and right hand sides; delete the old constraints afterwards
13567  */
13568  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13569  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13570  SCIPdebugPrintCons(scip, cons0, NULL);
13571  SCIPdebugPrintCons(scip, cons1, NULL);
13572 
13573  if( coefsequal )
13574  {
13575  /* the coefficients of both rows are equal */
13576  lhs = MAX(consdata0->lhs, consdata1->lhs);
13577  rhs = MIN(consdata0->rhs, consdata1->rhs);
13578  }
13579  else
13580  {
13581  /* the coefficients of both rows are negations */
13582  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13583  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13584  }
13585  if( SCIPisFeasLT(scip, rhs, lhs) )
13586  {
13587  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13588  *cutoff = TRUE;
13589  break;
13590  }
13591 
13592  /* check which constraint has to stay;
13593  * changes applied to an upgraded constraint will not be considered in the instance */
13594  if( consdata0->upgraded )
13595  {
13596  assert(!consdata1->upgraded);
13597  consstay = cons1;
13598 #ifndef NDEBUG
13599  consdatastay = consdata1;
13600 #endif
13601 
13602  consdel = cons0;
13603  consdatadel = consdata0;
13604  consinddel = chkind;
13605  }
13606  else
13607  {
13608  consstay = cons0;
13609 #ifndef NDEBUG
13610  consdatastay = consdata0;
13611 #endif
13612 
13613  consdel = cons1;
13614  consdatadel = consdata1;
13615  consinddel = c;
13616  }
13617 
13618  /* update the sides of consstay */
13619  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13620  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13621  if( !consdata0->upgraded )
13622  {
13623  assert(consstay == cons0);
13624  cons0lhs = consdata0->lhs;
13625  cons0rhs = consdata0->rhs;
13626  }
13627 
13628  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13629  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13630 
13631  assert( !consdatastay->upgraded );
13632  /* delete consdel */
13633  SCIP_CALL( SCIPdelCons(scip, consdel) );
13634  conss[consinddel] = NULL;
13635  if( !consdatadel->upgraded )
13636  (*ndelconss)++;
13637  continue;
13638  }
13639 
13640  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13641  * redundant
13642  */
13643  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13644  {
13645  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13646  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13647  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13648  SCIPdebugPrintCons(scip, cons0, NULL);
13649  SCIPdebugPrintCons(scip, cons1, NULL);
13650 
13651  /* check for infeasibility */
13652  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13653  {
13654  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13655  *cutoff = TRUE;
13656  break;
13657  }
13658 
13659  /* remove redundant left hand side */
13660  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13661  {
13662  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13663  cons0lhs = consdata0->lhs;
13664  cons0isequality = FALSE;
13665  if( !consdata0->upgraded )
13666  {
13667  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13668  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13669 
13670  (*nchgsides)++;
13671  }
13672  }
13673  }
13674  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13675  {
13676  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13677  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13678  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13679  SCIPdebugPrintCons(scip, cons1, NULL);
13680  SCIPdebugPrintCons(scip, cons0, NULL);
13681 
13682  /* check for infeasibility */
13683  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13684  {
13685  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13686  *cutoff = TRUE;
13687  break;
13688  }
13689 
13690  /* remove redundant left hand side */
13691  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13692  {
13693  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13694  cons1isequality = FALSE;
13695  if( !consdata1->upgraded )
13696  {
13697  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13698  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13699 
13700  (*nchgsides)++;
13701  }
13702  }
13703  }
13704  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13705  {
13706  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13707  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13708  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13709  SCIPdebugPrintCons(scip, cons0, NULL);
13710  SCIPdebugPrintCons(scip, cons1, NULL);
13711 
13712  /* check for infeasibility */
13713  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13714  {
13715  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13716  *cutoff = TRUE;
13717  break;
13718  }
13719 
13720  /* remove redundant right hand side */
13721  if( !SCIPisInfinity(scip, consdata0->rhs) )
13722  {
13723  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13724  cons0rhs = consdata0->rhs;
13725  cons0isequality = FALSE;
13726  if( !consdata0->upgraded )
13727  {
13728  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13729  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13730 
13731  (*nchgsides)++;
13732  }
13733  }
13734  }
13735  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13736  {
13737  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13738  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13739  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13740  SCIPdebugPrintCons(scip, cons1, NULL);
13741  SCIPdebugPrintCons(scip, cons0, NULL);
13742 
13743  /* check for infeasibility */
13744  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13745  {
13746  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13747  *cutoff = TRUE;
13748  break;
13749  }
13750 
13751  /* remove redundant right hand side */
13752  if( !SCIPisInfinity(scip, consdata1->rhs) )
13753  {
13754  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13755  cons1isequality = FALSE;
13756  if( !consdata1->upgraded )
13757  {
13758  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13759  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13760 
13761  (*nchgsides)++;
13762  }
13763  }
13764  }
13765 
13766  /* check for now redundant constraints */
13767  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13768  {
13769  /* consdata0 became redundant */
13770  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13771  SCIP_CALL( SCIPdelCons(scip, cons0) );
13772  conss[chkind] = NULL;
13773  if( !consdata0->upgraded )
13774  {
13775  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13776  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13777 
13778  (*ndelconss)++;
13779  }
13780  continue;
13781  }
13782  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13783  {
13784  /* consdata1 became redundant */
13785  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13786  SCIP_CALL( SCIPdelCons(scip, cons1) );
13787  conss[c] = NULL;
13788  if( !consdata1->upgraded )
13789  {
13790  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13791  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13792 
13793  (*ndelconss)++;
13794  }
13795  continue;
13796  }
13797 
13798  /* check, if we want to aggregate an (in)equality with an equality:
13799  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13800  */
13801  if( tryaggregation )
13802  {
13803  SCIP_Bool aggregated;
13804 
13805  assert(consdata0->nvars == nvarscommon + nvars0minus1);
13806  assert(consdata1->nvars == nvarscommon + nvars1minus0);
13807 
13808  aggregated = FALSE;
13809  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13810  {
13811  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13812  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13813  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13814  nchgcoefs, &aggregated, cutoff) );
13815 
13816  if( *cutoff )
13817  break;
13818 
13819  /* update array of active constraints */
13820  if( aggregated )
13821  {
13822  assert(!SCIPconsIsActive(cons0));
13823  assert(SCIPconsIsActive(cons1));
13824  conss[chkind] = NULL;
13825  }
13826  }
13827  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13828  {
13829  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13830  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13831  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13832  nchgcoefs, &aggregated, cutoff) );
13833 
13834  if( *cutoff )
13835  break;
13836 
13837  /* update array of active constraints */
13838  if( aggregated )
13839  {
13840  assert(!SCIPconsIsActive(cons1));
13841  assert(SCIPconsIsActive(cons0));
13842  conss[c] = NULL;
13843  }
13844  }
13845  }
13846  }
13847 
13848  /* free temporary memory */
13849  SCIPfreeBufferArray(scip, &diffidx1minus0);
13850  SCIPfreeBufferArray(scip, &diffidx0minus1);
13851  SCIPfreeBufferArray(scip, &commonidx1);
13852  SCIPfreeBufferArray(scip, &commonidx0);
13853 
13854  return SCIP_OKAY;
13855 }
13856 
13857 /** do stuffing presolving on a single constraint */
13858 static
13860  SCIP* scip, /**< SCIP data structure */
13861  SCIP_CONS* cons, /**< linear constraint */
13862  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13863  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13864  * constraints using the cheapest variable? */
13865  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13866  int* nfixedvars, /**< pointer to count the total number of fixed variables */
13867  int* nchgbds /**< pointer to count the total number of tightened bounds */
13868  )
13869 {
13870  SCIP_CONSDATA* consdata;
13871  SCIP_Real* ratios;
13872  int* varpos;
13873  SCIP_Bool* swapped;
13874  SCIP_VAR** vars;
13875  SCIP_Real* vals;
13876  SCIP_VAR* var;
13877  SCIP_Real lb;
13878  SCIP_Real ub;
13879  SCIP_Real minactivity;
13880  SCIP_Real maxactivity;
13881  SCIP_Real maxcondactivity;
13882  SCIP_Real mincondactivity;
13883  SCIP_Real rhs;
13884  SCIP_Real val;
13885  SCIP_Real obj;
13886  SCIP_Real factor;
13887  SCIP_Bool minactisrelax;
13888  SCIP_Bool maxactisrelax;
13889  SCIP_Bool tryfixing;
13890  int nsingletons;
13891  int idx;
13892  int v;
13893  int nvars;
13894 
13895  assert(scip != NULL);
13896  assert(cons != NULL);
13897  assert(nfixedvars != NULL);
13898 
13899  consdata = SCIPconsGetData(cons);
13900 
13901  /* we only want to run for inequalities */
13902  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13903  return SCIP_OKAY;
13904 
13905  if( singlevarstuffing )
13906  {
13907  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13908  }
13909  else
13910  {
13911  minactivity = SCIP_INVALID;
13912  maxactivity = SCIP_INVALID;
13913  }
13914 
13915  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13916  * the new maxactivity is minus the old minactivity then
13917  */
13918  if( SCIPisInfinity(scip, consdata->rhs) )
13919  {
13920  SCIP_Real tmp;
13921  rhs = -consdata->lhs;
13922  factor = -1.0;
13923  tmp = maxactivity;
13924  maxactivity = -minactivity;
13925  minactivity = -tmp;
13926  }
13927  else
13928  {
13929  assert(SCIPisInfinity(scip, -consdata->lhs));
13930  rhs = consdata->rhs;
13931  factor = 1.0;
13932  }
13933 
13934  nvars = consdata->nvars;
13935  vars = consdata->vars;
13936  vals = consdata->vals;
13937 
13938  /* check for continuous singletons */
13939  if( singletonstuffing )
13940  {
13941  for( v = 0; v < nvars; ++v )
13942  {
13943  var = vars[v];
13944 
13947  break;
13948  }
13949  }
13950  else
13951  /* we don't want to go into the next block */
13952  v = nvars;
13953 
13954  /* a singleton was found -> perform singleton variable stuffing */
13955  if( v < nvars )
13956  {
13957  assert(singletonstuffing);
13958 
13959  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
13960  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
13961  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
13962 
13963  tryfixing = TRUE;
13964  nsingletons = 0;
13965  mincondactivity = 0.0;
13966  maxcondactivity = 0.0;
13967 
13968  for( v = 0; v < nvars; ++v )
13969  {
13970  var = vars[v];
13971  lb = SCIPvarGetLbGlobal(var);
13972  ub = SCIPvarGetUbGlobal(var);
13973  obj = SCIPvarGetObj(var);
13974  val = factor * vals[v];
13975 
13976  assert(!SCIPisZero(scip, val));
13977 
13978  /* the variable is a singleton and continuous */
13981  {
13982  if( SCIPisNegative(scip, obj) && val > 0 )
13983  {
13984  /* case 1: obj < 0 and coef > 0 */
13985  if( SCIPisInfinity(scip, -lb) )
13986  {
13987  tryfixing = FALSE;
13988  break;
13989  }
13990 
13991  maxcondactivity += val * lb;
13992  mincondactivity += val * lb;
13993  swapped[v] = FALSE;
13994  ratios[nsingletons] = obj / val;
13995  varpos[nsingletons] = v;
13996  nsingletons++;
13997  }
13998  else if( SCIPisPositive(scip, obj) && val < 0 )
13999  {
14000  /* case 2: obj > 0 and coef < 0 */
14001  if( SCIPisInfinity(scip, ub) )
14002  {
14003  tryfixing = FALSE;
14004  break;
14005  }
14006  /* multiply column by (-1) to become case 1.
14007  * now bounds are swapped: ub := -lb, lb := -ub
14008  */
14009 
14010  maxcondactivity += val * ub;
14011  mincondactivity += val * ub;
14012  swapped[v] = TRUE;
14013  ratios[nsingletons] = obj / val;
14014  varpos[nsingletons] = v;
14015  nsingletons++;
14016  }
14017  else if( val > 0 )
14018  {
14019  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14020  * we only consider the lower bound for the constants
14021  */
14022  assert(!SCIPisNegative(scip, obj));
14023 
14024  if( SCIPisInfinity(scip, -lb) )
14025  {
14026  /* maybe unbounded */
14027  tryfixing = FALSE;
14028  break;
14029  }
14030 
14031  maxcondactivity += val * lb;
14032  mincondactivity += val * lb;
14033  }
14034  else
14035  {
14036  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14037  * we only consider the upper bound for the constants
14038  */
14039  assert(!SCIPisPositive(scip, obj));
14040  assert(val < 0);
14041 
14042  if( SCIPisInfinity(scip, ub) )
14043  {
14044  /* maybe unbounded */
14045  tryfixing = FALSE;
14046  break;
14047  }
14048 
14049  maxcondactivity += val * ub;
14050  mincondactivity += val * ub;
14051  }
14052  }
14053  else
14054  {
14055  /* consider contribution of discrete variables, non-singleton
14056  * continuous variables and variables with more than one lock
14057  */
14058  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14059  {
14060  tryfixing = FALSE;
14061  break;
14062  }
14063 
14064  if( val > 0 )
14065  {
14066  maxcondactivity += val * ub;
14067  mincondactivity += val * lb;
14068  }
14069  else
14070  {
14071  maxcondactivity += val * lb;
14072  mincondactivity += val * ub;
14073  }
14074  }
14075  }
14076  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14077  {
14078  SCIP_Real delta;
14079  SCIP_Bool tightened;
14080 #ifdef SCIP_DEBUG
14081  int oldnfixedvars = *nfixedvars;
14082  int oldnchgbds = *nchgbds;
14083 #endif
14084 
14085  SCIPsortRealInt(ratios, varpos, nsingletons);
14086 
14087  /* verify which singleton continuous variables can be fixed */
14088  for( v = 0; v < nsingletons; ++v )
14089  {
14090  idx = varpos[v];
14091  var = vars[idx];
14092  val = factor * vals[idx];
14093  lb = SCIPvarGetLbGlobal(var);
14094  ub = SCIPvarGetUbGlobal(var);
14095 
14096  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14097  assert((val < 0) == swapped[idx]);
14098  val = REALABS(val);
14099 
14100  /* stop fixing if variable bounds are not finite */
14101  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14102  break;
14103 
14106  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14107 
14108  /* calculate the change in the row activities if this variable changes
14109  * its value from its worst to its best bound
14110  */
14111  if( swapped[idx] )
14112  delta = -(lb - ub) * val;
14113  else
14114  delta = (ub - lb) * val;
14115 
14116  assert(!SCIPisNegative(scip, delta));
14117 
14118  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14119  {
14120  if( swapped[idx] )
14121  {
14122  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14123  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14124  }
14125  else
14126  {
14127  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14128  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14129  }
14130 
14131  if( *cutoff )
14132  break;
14133  if( tightened )
14134  {
14135  (*nfixedvars)++;
14136  }
14137  }
14138  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14139  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14140  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14141  * troubles in case of large bounds.
14142  */
14143  else if( SCIPisLE(scip, rhs, mincondactivity) )
14144  {
14145  if( swapped[idx] )
14146  {
14147  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14148  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14149  }
14150  else
14151  {
14152  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14153  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14154  }
14155 
14156  if( *cutoff )
14157  break;
14158  if( tightened )
14159  {
14160  (*nfixedvars)++;
14161  }
14162  }
14163 
14164  maxcondactivity += delta;
14165  mincondactivity += delta;
14166  }
14167 
14168 #ifdef SCIP_DEBUG
14169  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14170  {
14171  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14172  }
14173 #endif
14174  }
14175 
14176  SCIPfreeBufferArray(scip, &swapped);
14177  SCIPfreeBufferArray(scip, &ratios);
14178  SCIPfreeBufferArray(scip, &varpos);
14179  }
14180 
14181  /* perform single-variable stuffing:
14182  * for a linear inequality
14183  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14184  * with a_i > 0 and objective coefficients c_i < 0,
14185  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14186  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14187  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14188  * is redundant.
14189  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14190  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14191  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14192  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14193  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14194  * upper bound.
14195  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14196  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14197  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14198  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14199  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14200  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14201  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14202  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14203  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14204  * c_k * ceil((maxactivity - rhs)/val) is still better than
14205  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14206  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14207  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14208  * sign of coefficients in constraint and objective prevent the use of this method.
14209  */
14210  if( singlevarstuffing && !SCIPisInfinity(scip, -minactivity) )
14211  {
14212  SCIP_Real bestratio = -SCIPinfinity(scip);
14213  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14214  SCIP_Real ratio;
14215  int bestindex = -1;
14216  int bestuplocks = 0;
14217  int bestdownlocks = 1;
14218  int downlocks;
14219  int uplocks;
14220  int oldnfixedvars;
14221  int oldnchgbds;
14222 
14223  SCIPdebug( oldnfixedvars = *nfixedvars; )
14224  SCIPdebug( oldnchgbds = *nchgbds; )
14225  /* loop over all variables to identify the best and second-best ratio */
14226  for( v = 0; v < nvars; ++v )
14227  {
14228  var = vars[v];
14229  obj = SCIPvarGetObj(var);
14230  val = factor * vals[v];
14231 
14232  assert(!SCIPisZero(scip, val));
14233 
14234  ratio = obj / val;
14235 
14236  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14237  if( !SCIPisNegative(scip, ratio) )
14238  {
14239  bestindex = -1;
14240  break;
14241  }
14242 
14243  if( val > 0 )
14244  {
14247  }
14248  else
14249  {
14250  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14252  }
14253 
14254  /* better ratio, update best candidate
14255  * @todo use some tolerance
14256  * @todo check size of domain and updated ratio for integer variables already?
14257  */
14258  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14259  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14260  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14261  {
14262  /* best index becomes second-best*/
14263  if( bestindex != -1 )
14264  {
14265  /* second-best index must not have more than 1 uplock */
14266  if( bestuplocks > 1 )
14267  {
14268  bestindex = -1;
14269  break;
14270  }
14271  else
14272  {
14273  secondbestratio = bestratio;
14274  }
14275  }
14276  bestdownlocks = downlocks;
14277  bestuplocks = uplocks;
14278  bestratio = ratio;
14279  bestindex = v;
14280 
14281  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14282  * if it is not the best, it has too many uplocks -> not applicable
14283  */
14284  if( bestdownlocks > 0 && bestuplocks > 1 )
14285  {
14286  bestindex = -1;
14287  break;
14288  }
14289  }
14290  else
14291  {
14292  /* non-best index must not have more than 1 uplock */
14293  if( uplocks > 1 )
14294  {
14295  bestindex = -1;
14296  break;
14297  }
14298  /* update second-best ratio */
14299  if( ratio > secondbestratio )
14300  {
14301  secondbestratio = ratio;
14302  }
14303  }
14304  }
14305 
14306  /* check if we can apply single variable stuffing */
14307  if( bestindex != -1 && bestdownlocks == 0 )
14308  {
14309  SCIP_Bool tightened = FALSE;
14310  SCIP_Real bounddelta;
14311 
14312  var = vars[bestindex];
14313  obj = SCIPvarGetObj(var);
14314  val = factor * vals[bestindex];
14315  lb = SCIPvarGetLbGlobal(var);
14316  ub = SCIPvarGetUbGlobal(var);
14317  tryfixing = TRUE;
14318 
14319  if( val < 0 )
14320  {
14321  assert(!SCIPisNegative(scip, obj));
14322 
14323  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14324  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14325  {
14326  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14327  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14328  assert(SCIPisPositive(scip, activitydelta));
14329 
14330  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14331 
14332  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14333  assert(SCIPisPositive(scip, bounddelta));
14334  }
14335  else
14336  bounddelta = (maxactivity - rhs)/-val;
14337 
14338  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14339 
14340  if( tryfixing )
14341  {
14342  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14343 
14344  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14345  {
14346  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14347  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14348  }
14349  else
14350  {
14351  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14352  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14353  }
14354  }
14355  }
14356  else
14357  {
14358  assert(!SCIPisPositive(scip, obj));
14359 
14360  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14361  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14362  {
14363  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14364  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14365  assert(SCIPisPositive(scip, activitydelta));
14366 
14367  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14368 
14369  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14370  assert(SCIPisPositive(scip, bounddelta));
14371  }
14372  else
14373  bounddelta = (maxactivity - rhs)/val;
14374 
14375  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14376 
14377  if( tryfixing )
14378  {
14379  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14380 
14381  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14382  {
14383  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14384  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14385  }
14386  else
14387  {
14388  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14389  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14390  }
14391  }
14392  }
14393 
14394  if( *cutoff )
14395  return SCIP_OKAY;
14396  if( tightened )
14397  {
14398  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14399  ++(*nfixedvars);
14400  else
14401  ++(*nchgbds);
14402 
14403  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14404  for( v = 0; v < nvars; ++v )
14405  {
14406  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14407  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14410  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14411  }
14412  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14413 
14414  for( v = 0; v < nvars; ++v )
14415  {
14416  if( v == bestindex )
14417  continue;
14418 
14419  if( factor * vals[v] < 0 )
14420  {
14421  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14422  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14423  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14424  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14425  }
14426  else
14427  {
14428  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14429  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14430  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14431  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14432  }
14433 
14434  if( *cutoff )
14435  return SCIP_OKAY;
14436  if( tightened )
14437  ++(*nfixedvars);
14438  }
14439  SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14440  }
14441  }
14442  }
14443 
14444  return SCIP_OKAY;
14445 }
14446 
14447 /** applies full dual presolving on variables that only appear in linear constraints */
14448 static
14450  SCIP* scip, /**< SCIP data structure */
14451  SCIP_CONS** conss, /**< constraint set */
14452  int nconss, /**< number of constraints */
14453  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14454  int* nchgbds /**< pointer to count the number of bound changes */
14455  )
14456 {
14457  SCIP_Real* redlb;
14458  SCIP_Real* redub;
14459  int* nlocksdown;
14460  int* nlocksup;
14461  SCIP_Bool* isimplint;
14462  SCIP_VAR** origvars;
14463  SCIP_VAR** vars;
14464  SCIP_VAR** conscontvars;
14465  int nvars;
14466  int nbinvars;
14467  int nintvars;
14468  int ncontvars;
14469  int v;
14470  int c;
14471 
14472  /* we calculate redundancy bounds with the following meaning:
14473  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14474  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14475  * then:
14476  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14477  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14478  */
14479 
14480  /* Additionally, we detect continuous variables that are implicitly integral.
14481  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14482  * and all constraints (including the bounds as trivial constraints) in which:
14483  * c_j > 0: the variable is down-locked,
14484  * c_j < 0: the variable is up-locked,
14485  * c_j = 0: the variable appears
14486  * have, apart from j, only integer variables with integral coefficients and integral sides.
14487  * This is because then, the value of the variable is either determined by one of its bounds or
14488  * by one of these constraints, and in all cases, the value of the variable is integral.
14489  */
14490 
14491  assert(scip != NULL);
14492  assert(nconss == 0 || conss != NULL);
14493  assert(nchgbds != NULL);
14494  assert(!SCIPinProbing(scip));
14495 
14496  /* get active variables */
14497  nvars = SCIPgetNVars(scip);
14498  origvars = SCIPgetVars(scip);
14499 
14500  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14501  nbinvars = SCIPgetNBinVars(scip);
14502  if( nbinvars == nvars )
14503  return SCIP_OKAY;
14504 
14505  /* get number of continuous variables */
14506  ncontvars = SCIPgetNContVars(scip);
14507  nintvars = nvars - ncontvars;
14508 
14509  /* copy the variable array since this array might change during the curse of this algorithm */
14510  nvars = nvars - nbinvars;
14511  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14512 
14513  /* allocate temporary memory */
14514  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14515  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14516  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14517  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14518  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14519  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14520 
14521  /* initialize redundancy bounds */
14522  for( v = 0; v < nvars; ++v )
14523  {
14524  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14525  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14526  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14527  }
14528  BMSclearMemoryArray(nlocksdown, nvars);
14529  BMSclearMemoryArray(nlocksup, nvars);
14530 
14531  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14532  * We better not use SCIPisFeasIntegral() in these checks.
14533  */
14534  for( v = 0; v < ncontvars; v++ )
14535  {
14536  SCIP_VAR* var;
14537  SCIP_Real obj;
14538  SCIP_Real lb;
14539  SCIP_Real ub;
14540 
14541  var = vars[v + nintvars - nbinvars];
14542  lb = SCIPvarGetLbGlobal(var);
14543  ub = SCIPvarGetUbGlobal(var);
14544 
14545  obj = SCIPvarGetObj(var);
14546  if( SCIPisZero(scip, obj) )
14547  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14548  else
14549  {
14550  if( SCIPisPositive(scip, obj) )
14551  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14552  else
14553  {
14554  assert(SCIPisNegative(scip, obj));
14555  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14556  }
14557  }
14558  }
14559 
14560  /* scan all constraints */
14561  for( c = 0; c < nconss; ++c )
14562  {
14563  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14564  * part of checked disjunctions)
14565  */
14566  if( SCIPconsIsLocked(conss[c]) )
14567  {
14568  SCIP_CONSDATA* consdata;
14569  SCIP_Bool lhsexists;
14570  SCIP_Bool rhsexists;
14571  SCIP_Bool hasimpliedpotential;
14572  SCIP_Bool integralcoefs;
14573  int nlockspos;
14574  int contvarpos;
14575  int nconscontvars;
14576  int i;
14577 
14578  consdata = SCIPconsGetData(conss[c]);
14579  assert(consdata != NULL);
14580 
14581  /* get number of times the constraint was locked */
14582  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14583 
14584  /* we do not want to include constraints with locked negation (this would be too weird) */
14585  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14586  {
14587  /* mark all continuous variables as not being implicit integral */
14588  for( i = 0; i < consdata->nvars; ++i )
14589  {
14590  SCIP_VAR* var;
14591 
14592  var = consdata->vars[i];
14594  {
14595  int contv;
14596  contv = SCIPvarGetProbindex(var) - nintvars;
14597  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14598  isimplint[contv] = FALSE;
14599  }
14600  }
14601  continue;
14602  }
14603 
14604  /* check for existing sides */
14605  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14606  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14607 
14608  /* count locks and update redundancy bounds */
14609  contvarpos = -1;
14610  nconscontvars = 0;
14611  hasimpliedpotential = FALSE;
14612  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14613 
14614  for( i = 0; i < consdata->nvars; ++i )
14615  {
14616  SCIP_VAR* var;
14617  SCIP_Real val;
14618  SCIP_Real minresactivity;
14619  SCIP_Real maxresactivity;
14620  SCIP_Real newredlb;
14621  SCIP_Real newredub;
14622  SCIP_Bool minisrelax;
14623  SCIP_Bool maxisrelax;
14624  SCIP_Bool isminsettoinfinity;
14625  SCIP_Bool ismaxsettoinfinity;
14626  int arrayindex;
14627 
14628  var = consdata->vars[i];
14629  val = consdata->vals[i];
14630 
14631  /* check if still all integer variables have integral coefficients */
14632  if( SCIPvarIsIntegral(var) )
14633  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14634 
14635  /* we do not need to process binary variables */
14636  if( SCIPvarIsBinary(var) )
14637  continue;
14638 
14639  if( SCIPconsIsModifiable(conss[c]) )
14640  {
14641  minresactivity = -SCIPinfinity(scip);
14642  maxresactivity = SCIPinfinity(scip);
14643  isminsettoinfinity = TRUE;
14644  ismaxsettoinfinity = TRUE;
14645  }
14646  else
14647  {
14648  /* calculate residual activity bounds if variable would be fixed to zero */
14649  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14650  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14651 
14652  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14653  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14654  * This is needed, because we do not want to rely on relaxed finite resactivities.
14655  */
14656  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14657 
14658  /* check minresactivity for reliability */
14659  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14660  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14661 
14662  /* check maxresactivity for reliability */
14663  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14664  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14665  }
14666 
14667  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14668 
14669  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14670 
14671  newredlb = redlb[arrayindex];
14672  newredub = redub[arrayindex];
14673  if( val > 0.0 )
14674  {
14675  if( lhsexists )
14676  {
14677  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14678  nlocksdown[arrayindex] += nlockspos;
14679  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14680  }
14681  if( rhsexists )
14682  {
14683  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14684  nlocksup[arrayindex] += nlockspos;
14685  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14686  }
14687  }
14688  else
14689  {
14690  if( lhsexists )
14691  {
14692  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14693  nlocksup[arrayindex] += nlockspos;
14694  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14695  }
14696  if( rhsexists )
14697  {
14698  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14699  nlocksdown[arrayindex] += nlockspos;
14700  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14701  }
14702  }
14703 
14704  /* if the variable is integer, we have to round the value to the next integral value */
14705  if( SCIPvarIsIntegral(var) )
14706  {
14707  if( !SCIPisInfinity(scip, newredlb) )
14708  newredlb = SCIPceil(scip, newredlb);
14709  if( !SCIPisInfinity(scip, -newredub) )
14710  newredub = SCIPfloor(scip, newredub);
14711  }
14712 
14713  /* update redundancy bounds */
14714  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14715  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14716 
14717  /* collect the continuous variables of the constraint */
14719  {
14720  int contv;
14721 
14722  assert(nconscontvars < ncontvars);
14723  contvarpos = i;
14724  conscontvars[nconscontvars] = var;
14725  nconscontvars++;
14726 
14727  contv = SCIPvarGetProbindex(var) - nintvars;
14728  assert(0 <= contv && contv < ncontvars);
14729  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14730  }
14731  }
14732 
14733  /* update implied integer status of continuous variables */
14734  if( hasimpliedpotential )
14735  {
14736  if( nconscontvars > 1 || !integralcoefs )
14737  {
14738  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14739  * none of the continuous variables is implied integer
14740  */
14741  for( i = 0; i < nconscontvars; i++ )
14742  {
14743  int contv;
14744  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14745  assert(0 <= contv && contv < ncontvars);
14746  isimplint[contv] = FALSE;
14747  }
14748  }
14749  else
14750  {
14751  SCIP_VAR* var;
14752  SCIP_Real val;
14753  SCIP_Real absval;
14754  int contv;
14755 
14756  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14757  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14758  * side(s) of the constraint is integral
14759  */
14760  assert(nconscontvars == 1);
14761  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14762  var = consdata->vars[contvarpos];
14763  val = consdata->vals[contvarpos];
14764  contv = SCIPvarGetProbindex(var) - nintvars;
14765  assert(0 <= contv && contv < ncontvars);
14766  assert(isimplint[contv]);
14767 
14768  absval = REALABS(val);
14769  if( !SCIPisEQ(scip, absval, 1.0) )
14770  isimplint[contv] = FALSE;
14771  else
14772  {
14773  SCIP_Real obj;
14774 
14775  obj = SCIPvarGetObj(var);
14776  if( obj * val >= 0.0 && lhsexists )
14777  {
14778  /* the variable may be blocked by the constraint's left hand side */
14779  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14780  }
14781  if( obj * val <= 0.0 && rhsexists )
14782  {
14783  /* the variable may be blocked by the constraint's left hand side */
14784  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14785  }
14786  }
14787  }
14788  }
14789  }
14790  }
14791 
14792  /* check if any bounds can be tightened due to optimality */
14793  for( v = 0; v < nvars; ++v )
14794  {
14795  SCIP_VAR* var;
14796  SCIP_Real obj;
14797  SCIP_Bool infeasible;
14798  SCIP_Bool tightened;
14799 
14800  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14801  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14802  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14803 
14804  var = vars[v];
14805  obj = SCIPvarGetObj(var);
14806  if( obj >= 0.0 )
14807  {
14808  /* making the variable as small as possible does not increase the objective:
14809  * check if all down locks of the variables are due to linear constraints;
14810  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14811  */
14812  if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14813  && !SCIPisInfinity(scip, -redlb[v])
14814  && redlb[v] < SCIPvarGetUbGlobal(var) )
14815  {
14816  SCIP_Real ub;
14817 
14818  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14819  * -> tighten upper bound to x_v <= redlb[v]
14820  */
14821  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14823  redlb[v]);
14824  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14825  assert(!infeasible);
14826 
14827  ub = SCIPvarGetUbGlobal(var);
14828  redub[v] = MIN(redub[v], ub);
14829  if( tightened )
14830  (*nchgbds)++;
14831  }
14832  }
14833  if( obj <= 0.0 )
14834  {
14835  /* making the variable as large as possible does not increase the objective:
14836  * check if all up locks of the variables are due to linear constraints;
14837  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14838  */
14839  if( SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14840  && !SCIPisInfinity(scip, redub[v])
14841  && redub[v] > SCIPvarGetLbGlobal(var) )
14842  {
14843  SCIP_Real lb;
14844 
14845  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14846  * -> tighten lower bound to x_v >= redub[v]
14847  */
14848  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14850  redub[v]);
14851  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14852  assert(!infeasible);
14853 
14854  lb = SCIPvarGetLbGlobal(var);
14855  redlb[v] = MAX(redlb[v], lb);
14856  if( tightened )
14857  (*nchgbds)++;
14858  }
14859  }
14860  }
14861 
14862  /* upgrade continuous variables to implied integers */
14863  for( v = nintvars - nbinvars; v < nvars; ++v )
14864  {
14865  SCIP_VAR* var;
14866  SCIP_Bool infeasible;
14867 
14868  var = vars[v];
14869  assert(var != NULL);
14870 
14871  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14872  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14873  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14874  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14875 
14876  /* we can only conclude implied integrality if the variable appears in no other constraint */
14877  if( isimplint[v - nintvars + nbinvars]
14878  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14879  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
14880  {
14881  /* since we locally copied the variable array we can change the variable type immediately */
14882  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
14883 
14884  if( infeasible )
14885  {
14886  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14887  *cutoff = TRUE;
14888 
14889  break;
14890  }
14891 
14892  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
14894  }
14895  }
14896 
14897  /* free temporary memory */
14898  SCIPfreeBufferArray(scip, &conscontvars);
14899  SCIPfreeBufferArray(scip, &isimplint);
14900  SCIPfreeBufferArray(scip, &nlocksup);
14901  SCIPfreeBufferArray(scip, &nlocksdown);
14902  SCIPfreeBufferArray(scip, &redub);
14903  SCIPfreeBufferArray(scip, &redlb);
14904 
14905  SCIPfreeBufferArray(scip, &vars);
14906 
14907  return SCIP_OKAY;
14908 }
14909 
14910 /** helper function to enforce constraints */
14911 static
14913  SCIP* scip, /**< SCIP data structure */
14914  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14915  SCIP_CONS** conss, /**< constraints to process */
14916  int nconss, /**< number of constraints */
14917  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14918  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14919  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14920  )
14921 {
14922  SCIP_CONSHDLRDATA* conshdlrdata;
14923  SCIP_Bool checkrelmaxabs;
14924  SCIP_Bool violated;
14925  SCIP_Bool cutoff = FALSE;
14926  int c;
14927 
14928  assert(scip != NULL);
14929  assert(conshdlr != NULL);
14930  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14931  assert(result != NULL);
14932 
14933  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14934  assert(conshdlrdata != NULL);
14935 
14936  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14937 
14938  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14939 
14940  /* check for violated constraints
14941  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14942  */
14943  *result = SCIP_FEASIBLE;
14944 
14945  /* check all useful linear constraints for feasibility */
14946  for( c = 0; c < nusefulconss; ++c )
14947  {
14948  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14949 
14950  if( violated )
14951  {
14952  /* insert LP row as cut */
14953  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14954  if ( cutoff )
14955  *result = SCIP_CUTOFF;
14956  else
14957  *result = SCIP_SEPARATED;
14958  }
14959  }
14960 
14961  /* check all obsolete linear constraints for feasibility */
14962  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14963  {
14964  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14965 
14966  if( violated )
14967  {
14968  /* insert LP row as cut */
14969  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
14970  if ( cutoff )
14971  *result = SCIP_CUTOFF;
14972  else
14973  *result = SCIP_SEPARATED;
14974  }
14975  }
14976 
14977  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
14978 
14979  return SCIP_OKAY;
14980 }
14981 
14982 /*
14983  * Callback methods of constraint handler
14984  */
14985 
14986 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
14987 static
14988 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
14989 { /*lint --e{715}*/
14990  assert(scip != NULL);
14991  assert(conshdlr != NULL);
14992  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14993 
14994  /* call inclusion method of constraint handler */
14996 
14997  *valid = TRUE;
14998 
14999  return SCIP_OKAY;
15000 }
15001 
15002 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15003 static
15004 SCIP_DECL_CONSFREE(consFreeLinear)
15005 { /*lint --e{715}*/
15006  SCIP_CONSHDLRDATA* conshdlrdata;
15007 
15008  assert(scip != NULL);
15009  assert(conshdlr != NULL);
15010  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15011 
15012  /* free constraint handler data */
15013  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15014  assert(conshdlrdata != NULL);
15015 
15016  conshdlrdataFree(scip, &conshdlrdata);
15017 
15018  SCIPconshdlrSetData(conshdlr, NULL);
15019 
15020  return SCIP_OKAY;
15022 
15023 
15024 /** initialization method of constraint handler (called after problem was transformed) */
15025 static
15026 SCIP_DECL_CONSINIT(consInitLinear)
15027 {
15028  SCIP_CONSHDLRDATA* conshdlrdata;
15029  int c;
15030 
15031  assert(scip != NULL);
15032 
15033  /* check for event handler */
15034  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15035  assert(conshdlrdata != NULL);
15036  assert(conshdlrdata->eventhdlr != NULL);
15037  assert(nconss == 0 || conss != NULL);
15038 
15039  /* catch events for the constraints */
15040  for( c = 0; c < nconss; ++c )
15041  {
15042  /* catch all events */
15043  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15044  }
15045 
15046  return SCIP_OKAY;
15047 }
15048 
15049 
15050 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15051 static
15052 SCIP_DECL_CONSEXIT(consExitLinear)
15053 {
15054  SCIP_CONSHDLRDATA* conshdlrdata;
15055  int c;
15056 
15057  assert(scip != NULL);
15058 
15059  /* check for event handler */
15060  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15061  assert(conshdlrdata != NULL);
15062  assert(conshdlrdata->eventhdlr != NULL);
15063 
15064  /* drop events for the constraints */
15065  for( c = nconss - 1; c >= 0; --c )
15066  {
15067  SCIP_CONSDATA* consdata;
15068 
15069  consdata = SCIPconsGetData(conss[c]);
15070  assert(consdata != NULL);
15071 
15072  if( consdata->eventdata != NULL )
15073  {
15074  /* drop all events */
15075  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15076  assert(consdata->eventdata == NULL);
15077  }
15078  }
15079 
15080  return SCIP_OKAY;
15081 }
15082 
15083 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15084 static
15086  SCIP* scip, /**< SCIP data structure */
15087  SCIP_Real lhs, /**< left hand side */
15088  SCIP_Real rhs /**< right hand side */
15089  )
15090 {
15091  assert(scip != NULL);
15092 
15093  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15094 }
15095 
15096 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15097 static
15099  SCIP* scip, /**< SCIP data structure */
15100  SCIP_Real x /**< value */
15101  )
15103  assert(scip != NULL);
15104 
15105  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15106 }
15107 
15108 /** performs linear constraint type classification as used for MIPLIB
15109  *
15110  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15111  *
15112  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15113  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15114  * Similarly, if specialized constraints were created through the API, these are currently not present.
15115  */
15117  SCIP* scip, /**< SCIP data structure */
15118  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15119  )
15120 {
15121  int c;
15122  SCIP_CONSHDLR* conshdlr;
15123  SCIP_CONS** conss;
15124  int nconss;
15125 
15126  assert(scip != NULL);
15127  assert(linconsstats != NULL);
15128  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15129  assert(conshdlr != NULL);
15130 
15131  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15132  {
15133  conss = SCIPgetConss(scip);
15134  nconss = SCIPgetNConss(scip);
15135  }
15136  else
15137  {
15138  conss = SCIPconshdlrGetConss(conshdlr);
15139  nconss = SCIPconshdlrGetNConss(conshdlr);
15140  }
15141 
15142  /* reset linear constraint type classification */
15143  SCIPlinConsStatsReset(linconsstats);
15144 
15145  /* loop through all constraints */
15146  for( c = 0; c < nconss; c++ )
15147  {
15148  SCIP_CONS* cons;
15149  SCIP_CONSDATA* consdata;
15150  SCIP_Real lhs;
15151  SCIP_Real rhs;
15152  int i;
15153 
15154  /* get constraint */
15155  cons = conss[c];
15156  assert(cons != NULL);
15157 
15158  /* skip constraints that are not handled by the constraint handler */
15159  if( SCIPconsGetHdlr(cons) != conshdlr )
15160  continue;
15161 
15162  /* get constraint data */
15163  consdata = SCIPconsGetData(cons);
15164  assert(consdata != NULL);
15165  rhs = consdata->rhs;
15166  lhs = consdata->lhs;
15167 
15168  /* merge multiples and delete variables with zero coefficient */
15169  SCIP_CALL( mergeMultiples(scip, cons) );
15170  for( i = 0; i < consdata->nvars; i++ )
15171  {
15172  assert(!SCIPisZero(scip, consdata->vals[i]));
15173  }
15174 
15175  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15176  if( consdata->nvars == 0 )
15177  {
15178  SCIPdebugMsg(scip, "classified as EMPTY: ");
15179  SCIPdebugPrintCons(scip, cons, NULL);
15181 
15182  continue;
15183  }
15184 
15185  /* is constraint of type SCIP_CONSTYPE_FREE? */
15186  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15187  {
15188  SCIPdebugMsg(scip, "classified as FREE: ");
15189  SCIPdebugPrintCons(scip, cons, NULL);
15191 
15192  continue;
15193  }
15194 
15195  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15196  if( consdata->nvars == 1 )
15197  {
15198  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15199  SCIPdebugPrintCons(scip, cons, NULL);
15200  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15201 
15202  continue;
15203  }
15204 
15205  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15206  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15207  {
15208  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15209  SCIPdebugPrintCons(scip, cons, NULL);
15211 
15212  continue;
15213  }
15214 
15215  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15216  if( consdata->nvars == 2 )
15217  {
15218  SCIP_LINCONSTYPE constype;
15219 
15220  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15221  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15222  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15223  {
15224  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15225  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15226  }
15227  else
15228  {
15229  constype = SCIP_LINCONSTYPE_VARBOUND;
15230  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15231  }
15232  SCIPdebugPrintCons(scip, cons, NULL);
15233 
15234  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15235 
15236  continue;
15237  }
15238 
15239  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15240  {
15241  SCIP_Real scale;
15242  SCIP_Real b;
15243  SCIP_Bool unmatched;
15244  int nnegbinvars;
15245 
15246  unmatched = FALSE;
15247  nnegbinvars = 0;
15248 
15249  scale = REALABS(consdata->vals[0]);
15250 
15251  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15252  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15253  {
15254  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15255  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15256  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15257  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15258 
15259  if( consdata->vals[i] < 0.0 )
15260  nnegbinvars++;
15261  }
15262 
15263  if( !unmatched )
15264  {
15265  if( SCIPisEQ(scip, lhs, rhs) )
15266  {
15267  b = rhs/scale + nnegbinvars;
15268  if( SCIPisEQ(scip, 1.0, b) )
15269  {
15270  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15271  SCIPdebugPrintCons(scip, cons, NULL);
15273 
15274  continue;
15275  }
15276  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15277  {
15278  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15279  SCIPdebugPrintCons(scip, cons, NULL);
15281 
15282  continue;
15283  }
15284  }
15285 
15286  /* compute right hand side divided by scale */
15287  if( !SCIPisInfinity(scip, rhs) )
15288  b = rhs/scale + nnegbinvars;
15289  else
15290  b = SCIPinfinity(scip);
15291 
15292  if( SCIPisEQ(scip, 1.0, b) )
15293  {
15294  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15295  SCIPdebugPrintCons(scip, cons, NULL);
15297 
15298  /* relax right hand side to prevent further classifications */
15299  rhs = SCIPinfinity(scip);
15300  }
15301  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15302  {
15303  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15304  SCIPdebugPrintCons(scip, cons, NULL);
15305 
15307 
15308  /* relax right hand side to prevent further classifications */
15309  rhs = SCIPinfinity(scip);
15310  }
15311 
15312  if( !SCIPisInfinity(scip, lhs) )
15313  b = lhs/scale + nnegbinvars;
15314  else
15315  b = SCIPinfinity(scip);
15316 
15317  if( SCIPisEQ(scip, 1.0, b) )
15318  {
15319  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15320  SCIPdebugPrintCons(scip, cons, NULL);
15322 
15323  /* relax left hand side to prevent further classifications */
15324  lhs = -SCIPinfinity(scip);
15325  }
15326 
15327  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15328  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15329  continue;
15330  }
15331  }
15332 
15333  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15334  /* @todo If coefficients or rhs are not integral, we currently do not check
15335  * if the constraint could be scaled (finitely), such that they are.
15336  */
15337  {
15338  SCIP_Real b;
15339  SCIP_Bool unmatched;
15340 
15341  b = rhs;
15342  unmatched = FALSE;
15343  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15344  {
15345  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15346  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15347  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15348  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15349 
15350  if( SCIPisNegative(scip, consdata->vals[i]) )
15351  b -= consdata->vals[i];
15352  }
15353  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15354 
15355  if( !unmatched )
15356  {
15357  if( SCIPisEQ(scip, lhs, rhs) )
15358  {
15359  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15360  SCIPdebugPrintCons(scip, cons, NULL);
15361 
15363 
15364  continue;
15365  }
15366  else
15367  {
15368  SCIP_Bool matched;
15369 
15370  matched = FALSE;
15371  for( i = 0; i < consdata->nvars && !matched; i++ )
15372  {
15373  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15374  }
15375 
15376  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15377  SCIPdebugPrintCons(scip, cons, NULL);
15379  }
15380 
15381  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15382  if( SCIPisInfinity(scip, -lhs) )
15383  continue;
15384  else
15385  rhs = SCIPinfinity(scip);
15386  }
15387  }
15388 
15389  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15390  {
15391  SCIP_Real b;
15392  SCIP_Bool unmatched;
15393 
15394  unmatched = FALSE;
15395 
15396  b = rhs;
15397  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15398 
15399  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15400  {
15401  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15402  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15403  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15404  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15405  }
15406 
15407  if( !unmatched )
15408  {
15409  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15410  SCIPdebugPrintCons(scip, cons, NULL);
15412 
15413  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15414  if( SCIPisInfinity(scip, -lhs) )
15415  continue;
15416  else
15417  rhs = SCIPinfinity(scip);
15418  }
15419  }
15420 
15421  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15422  {
15423  SCIP_Bool unmatched;
15424 
15425  unmatched = FALSE;
15426  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15427  {
15428  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15429  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15430  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15431  unmatched = TRUE;
15432  }
15433 
15434  if( !unmatched )
15435  {
15436  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15437  SCIPdebugPrintCons(scip, cons, NULL);
15438  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15439 
15440  continue;
15441  }
15442  }
15443 
15444  /* no special structure detected */
15445  SCIPdebugMsg(scip, "classified as GENERAL: ");
15446  SCIPdebugPrintCons(scip, cons, NULL);
15447  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15448  }
15449 
15450  return SCIP_OKAY;
15451 }
15452 
15453 
15454 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15455 static
15456 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15457 { /*lint --e{715}*/
15458  int c;
15459 #ifdef SCIP_STATISTIC
15460  SCIP_CONSHDLRDATA* conshdlrdata;
15461  int ngoodconss;
15462  int nallconss;
15463 #endif
15464 
15465  /* delete all linear constraints that were upgraded to a more specific constraint type;
15466  * make sure, only active variables remain in the remaining constraints
15467  */
15468  assert(scip != NULL);
15469 
15470 #ifdef SCIP_STATISTIC
15471  /* count number of well behaved linear constraints */
15472  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15473  assert(conshdlrdata != NULL);
15474 
15475  ngoodconss = 0;
15476  nallconss = 0;
15477 
15478  for( c = 0; c < nconss; ++c )
15479  {
15480  SCIP_CONSDATA* consdata;
15481 
15482  if( SCIPconsIsDeleted(conss[c]) )
15483  continue;
15484 
15485  consdata = SCIPconsGetData(conss[c]);
15486  assert(consdata != NULL);
15487 
15488  if( consdata->upgraded )
15489  continue;
15490 
15491  nallconss++;
15492 
15493  consdataRecomputeMaxActivityDelta(scip, consdata);
15494 
15495  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15496  ngoodconss++;
15497  }
15498  if( nallconss )
15499  {
15500  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15501  }
15502 #endif
15503 
15504  for( c = 0; c < nconss; ++c )
15505  {
15506  SCIP_CONSDATA* consdata;
15507 
15508  if( SCIPconsIsDeleted(conss[c]) )
15509  continue;
15510 
15511  consdata = SCIPconsGetData(conss[c]);
15512  assert(consdata != NULL);
15513 
15514  if( consdata->upgraded )
15515  {
15516  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15517  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15518  */
15519  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15520  }
15521  else
15522  {
15523  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15524  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15525  }
15526  }
15527 
15528  return SCIP_OKAY;
15529 }
15530 
15531 
15532 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15533 static
15534 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15535 { /*lint --e{715}*/
15536  int c;
15537 
15538  assert(scip != NULL);
15539 
15540  /* release the rows of all constraints */
15541  for( c = 0; c < nconss; ++c )
15542  {
15543  SCIP_CONSDATA* consdata;
15544 
15545  consdata = SCIPconsGetData(conss[c]);
15546  assert(consdata != NULL);
15547 
15548  if( consdata->row != NULL )
15549  {
15550  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15551  }
15552  }
15553 
15554  /* if this is a restart, convert cutpool rows into linear constraints */
15555  if( restart )
15556  {
15557  int ncutsadded;
15558 
15559  ncutsadded = 0;
15560 
15561  /* create out of all active cuts in cutpool linear constraints */
15562  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15563 
15564  if( ncutsadded > 0 )
15565  {
15567  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15568  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15569  * line correctly
15570  */
15572  }
15573  }
15574 
15575  return SCIP_OKAY;
15576 }
15577 
15578 
15579 /** constraint deactivation notification method of constraint handler */
15580 static
15581 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15582 { /*lint --e{715}*/
15583  assert( cons != NULL );
15584 
15585  if( SCIPconsIsDeleted(cons) )
15586  {
15587  SCIP_CONSHDLRDATA* conshdlrdata;
15588  SCIP_CONSDATA* consdata;
15589 
15590  assert(scip != NULL);
15591  assert(conshdlr != NULL);
15592  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15593 
15594  /* get constraint data */
15595  consdata = SCIPconsGetData(cons);
15596  assert(consdata != NULL);
15597 
15598  /* check for event handler */
15599  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15600  assert(conshdlrdata != NULL);
15601  assert(conshdlrdata->eventhdlr != NULL);
15602 
15603  /* free event data */
15604  if( consdata->eventdata != NULL )
15605  {
15606  /* drop bound change events of variables */
15607  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15608  }
15609  assert(consdata->eventdata == NULL);
15610  }
15611 
15612  return SCIP_OKAY;
15613 }
15614 
15615 
15616 /** frees specific constraint data */
15617 static
15618 SCIP_DECL_CONSDELETE(consDeleteLinear)
15619 { /*lint --e{715}*/
15620  assert(scip != NULL);
15621  assert(conshdlr != NULL);
15622  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15623 
15624  if( (*consdata)->eventdata != NULL )
15625  {
15626  SCIP_CONSHDLRDATA* conshdlrdata;
15627 
15628  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15629  assert(conshdlrdata != NULL);
15630 
15631  /* drop all events */
15632  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15633  assert((*consdata)->eventdata == NULL);
15634  }
15636  /* free linear constraint */
15637  SCIP_CALL( consdataFree(scip, consdata) );
15638 
15639  return SCIP_OKAY;
15640 }
15641 
15642 
15643 /** transforms constraint data into data belonging to the transformed problem */
15644 static
15645 SCIP_DECL_CONSTRANS(consTransLinear)
15646 { /*lint --e{715}*/
15647  SCIP_CONSDATA* sourcedata;
15648  SCIP_CONSDATA* targetdata;
15649 
15650  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15651 
15652  assert(scip != NULL);
15653  assert(conshdlr != NULL);
15654  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15655  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15656  assert(sourcecons != NULL);
15657  assert(targetcons != NULL);
15658 
15659  sourcedata = SCIPconsGetData(sourcecons);
15660  assert(sourcedata != NULL);
15661  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15663  /* create linear constraint data for target constraint */
15664  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15665 
15666  /* create target constraint */
15667  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15668  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15669  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15670  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15671  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15672 
15673  return SCIP_OKAY;
15674 }
15675 
15676 
15677 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15678 static
15679 SCIP_DECL_CONSINITLP(consInitlpLinear)
15680 { /*lint --e{715}*/
15681  int c;
15682 
15683  assert(scip != NULL);
15684  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15685 
15686  *infeasible = FALSE;
15687 
15688  for( c = 0; c < nconss && !(*infeasible); ++c )
15689  {
15690  assert(SCIPconsIsInitial(conss[c]));
15691  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15692  }
15693 
15694  return SCIP_OKAY;
15695 }
15697 
15698 /** separation method of constraint handler for LP solutions */
15699 static
15700 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15701 { /*lint --e{715}*/
15702  SCIP_CONSHDLRDATA* conshdlrdata;
15703  SCIP_Real loclowerbound;
15704  SCIP_Real glblowerbound;
15705  SCIP_Real cutoffbound;
15706  SCIP_Real maxbound;
15707  SCIP_Bool separatecards;
15708  SCIP_Bool cutoff;
15709  int c;
15710  int depth;
15711  int nrounds;
15712  int maxsepacuts;
15713  int ncuts;
15714 
15715  assert(scip != NULL);
15716  assert(conshdlr != NULL);
15717  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15718  assert(result != NULL);
15719 
15720  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15721  assert(conshdlrdata != NULL);
15722  depth = SCIPgetDepth(scip);
15723  nrounds = SCIPgetNSepaRounds(scip);
15724 
15725  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15726 
15727  *result = SCIP_DIDNOTRUN;
15728 
15729  /* only call the separator a given number of times at each node */
15730  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15731  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15732  return SCIP_OKAY;
15733 
15734  /* get the maximal number of cuts allowed in a separation round */
15735  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15736 
15737  /* check if we want to produce knapsack cardinality cuts at this node */
15738  loclowerbound = SCIPgetLocalLowerbound(scip);
15739  glblowerbound = SCIPgetLowerbound(scip);
15740  cutoffbound = SCIPgetCutoffbound(scip);
15741  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15742  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15743  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15744 
15745  *result = SCIP_DIDNOTFIND;
15746  ncuts = 0;
15747  cutoff = FALSE;
15748 
15749  /* check all useful linear constraints for feasibility */
15750  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15751  {
15752  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15753  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15754  }
15755 
15756  /* adjust return value */
15757  if( cutoff )
15758  *result = SCIP_CUTOFF;
15759  else if( ncuts > 0 )
15760  *result = SCIP_SEPARATED;
15761 
15762  /* combine linear constraints to get more cuts */
15763  /**@todo further cuts of linear constraints */
15764 
15765  return SCIP_OKAY;
15766 }
15767 
15768 
15769 /** separation method of constraint handler for arbitrary primal solutions */
15770 static
15771 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15772 { /*lint --e{715}*/
15773  SCIP_CONSHDLRDATA* conshdlrdata;
15774  int c;
15775  int depth;
15776  int nrounds;
15777  int maxsepacuts;
15778  int ncuts;
15779  SCIP_Bool cutoff;
15780 
15781  assert(scip != NULL);
15782  assert(conshdlr != NULL);
15783  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15784  assert(result != NULL);
15785 
15786  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15787  assert(conshdlrdata != NULL);
15788  depth = SCIPgetDepth(scip);
15789  nrounds = SCIPgetNSepaRounds(scip);
15790 
15791  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15792 
15793  *result = SCIP_DIDNOTRUN;
15794 
15795  /* only call the separator a given number of times at each node */
15796  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15797  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15798  return SCIP_OKAY;
15799 
15800  /* get the maximal number of cuts allowed in a separation round */
15801  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15802 
15803  *result = SCIP_DIDNOTFIND;
15804  ncuts = 0;
15805  cutoff = FALSE;
15806 
15807  /* check all useful linear constraints for feasibility */
15808  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15809  {
15810  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15811  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15812  }
15813 
15814  /* adjust return value */
15815  if( cutoff )
15816  *result = SCIP_CUTOFF;
15817  else if( ncuts > 0 )
15818  *result = SCIP_SEPARATED;
15819 
15820  /* combine linear constraints to get more cuts */
15821  /**@todo further cuts of linear constraints */
15822 
15823  return SCIP_OKAY;
15824 }
15825 
15826 
15827 /** constraint enforcing method of constraint handler for LP solutions */
15828 static
15829 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15830 { /*lint --e{715}*/
15831  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15832 
15833  return SCIP_OKAY;
15834 }
15835 
15836 /** constraint enforcing method of constraint handler for relaxation solutions */
15837 static
15838 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15839 { /*lint --e{715}*/
15840  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15841 
15842  return SCIP_OKAY;
15843 }
15844 
15845 /** constraint enforcing method of constraint handler for pseudo solutions */
15846 static
15847 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15848 { /*lint --e{715}*/
15849  SCIP_CONSHDLRDATA* conshdlrdata;
15850  SCIP_Bool checkrelmaxabs;
15851  SCIP_Bool violated;
15852  int c;
15853 
15854  assert(scip != NULL);
15855  assert(conshdlr != NULL);
15856  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15857  assert(result != NULL);
15858 
15859  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15860  assert(conshdlrdata != NULL);
15861 
15862  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15863 
15864  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15865 
15866  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
15867  if( objinfeasible )
15868  {
15869  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
15870 
15871  *result = SCIP_DIDNOTRUN;
15872  return SCIP_OKAY;
15873  }
15874 
15875  /* check all linear constraints for feasibility */
15876  violated = FALSE;
15877  for( c = 0; c < nconss && !violated; ++c )
15878  {
15879  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
15880  }
15881 
15882  if( violated )
15883  *result = SCIP_INFEASIBLE;
15884  else
15885  *result = SCIP_FEASIBLE;
15886 
15887  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15888 
15889  return SCIP_OKAY;
15890 }
15891 
15892 
15893 /** feasibility check method of constraint handler for integral solutions */
15894 static
15895 SCIP_DECL_CONSCHECK(consCheckLinear)
15896 { /*lint --e{715}*/
15897  SCIP_CONSHDLRDATA* conshdlrdata;
15898  SCIP_Bool checkrelmaxabs;
15899  int c;
15900 
15901  assert(scip != NULL);
15902  assert(conshdlr != NULL);
15903  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15904  assert(result != NULL);
15905 
15906  *result = SCIP_FEASIBLE;
15907 
15908  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15909  assert(conshdlrdata != NULL);
15910 
15911  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15913  /*debugMsg(scip, "Check method of linear constraints\n");*/
15914 
15915  /* check all linear constraints for feasibility */
15916  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
15917  {
15918  SCIP_Bool violated = FALSE;
15919  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
15920 
15921  if( violated )
15922  {
15923  *result = SCIP_INFEASIBLE;
15924 
15925  if( printreason )
15926  {
15927  SCIP_CONSDATA* consdata;
15928  SCIP_Real activity;
15929 
15930  consdata = SCIPconsGetData(conss[c]);
15931  assert( consdata != NULL);
15932 
15933  activity = consdataGetActivity(scip, consdata, sol);
15934 
15935  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
15936  SCIPinfoMessage(scip, NULL, ";\n");
15937 
15938  if( activity == SCIP_INVALID ) /*lint !e777*/
15939  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
15940  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
15941  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
15942  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
15943  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
15944  }
15945  }
15946  }
15947 
15948  return SCIP_OKAY;
15949 }
15950 
15951 
15952 /** domain propagation method of constraint handler */
15953 static
15954 SCIP_DECL_CONSPROP(consPropLinear)
15955 { /*lint --e{715}*/
15956  SCIP_CONSHDLRDATA* conshdlrdata;
15957  SCIP_Bool rangedrowpropagation = FALSE;
15958  SCIP_Bool tightenbounds;
15959  SCIP_Bool cutoff;
15960 
15961  int nchgbds;
15962  int i;
15963 
15964  assert(scip != NULL);
15965  assert(conshdlr != NULL);
15966  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15967  assert(result != NULL);
15968 
15969  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15970  assert(conshdlrdata != NULL);
15972  /*debugMsg(scip, "Prop method of linear constraints\n");*/
15973 
15974  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
15975  if( SCIPinProbing(scip) )
15976  tightenbounds = TRUE;
15977  else
15978  {
15979  int depth;
15980  int propfreq;
15981  int tightenboundsfreq;
15982  int rangedrowfreq;
15983 
15984  depth = SCIPgetDepth(scip);
15985  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
15986  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
15987  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
15988  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
15989 
15990  /* check if we want to do ranged row propagation */
15991  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
15992  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
15993  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
15994  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
15995  rangedrowpropagation = rangedrowpropagation && (depth % rangedrowfreq == 0);
15996  }
15997 
15998  cutoff = FALSE;
15999  nchgbds = 0;
16000 
16001  /* process constraints marked for propagation */
16002  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16003  {
16004  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16005  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16006  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16007  }
16008 
16009  /* adjust result code */
16010  if( cutoff )
16011  *result = SCIP_CUTOFF;
16012  else if( nchgbds > 0 )
16013  *result = SCIP_REDUCEDDOM;
16014  else
16015  *result = SCIP_DIDNOTFIND;
16016 
16017  return SCIP_OKAY;
16018 }
16019 
16020 
16021 #define MAXCONSPRESOLROUNDS 10
16022 /** presolving method of constraint handler */
16023 static
16024 SCIP_DECL_CONSPRESOL(consPresolLinear)
16025 { /*lint --e{715}*/
16026  SCIP_CONSHDLRDATA* conshdlrdata;
16027  SCIP_CONS* cons;
16028  SCIP_CONSDATA* consdata;
16029  SCIP_Real minactivity;
16030  SCIP_Real maxactivity;
16031  SCIP_Bool minactisrelax;
16032  SCIP_Bool maxactisrelax;
16033  SCIP_Bool cutoff;
16034  int oldnfixedvars;
16035  int oldnaggrvars;
16036  int oldnchgbds;
16037  int oldndelconss;
16038  int oldnupgdconss;
16039  int oldnchgcoefs;
16040  int oldnchgsides;
16041  int firstchange;
16042  int firstupgradetry;
16043  int c;
16044 
16045  assert(scip != NULL);
16046  assert(conshdlr != NULL);
16047  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16048  assert(result != NULL);
16049 
16050  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16051 
16052  /* remember old preprocessing counters */
16053  cutoff = FALSE;
16054  oldnfixedvars = *nfixedvars;
16055  oldnaggrvars = *naggrvars;
16056  oldnchgbds = *nchgbds;
16057  oldndelconss = *ndelconss;
16058  oldnupgdconss = *nupgdconss;
16059  oldnchgcoefs = *nchgcoefs;
16060  oldnchgsides = *nchgsides;
16061 
16062  /* get constraint handler data */
16063  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16064  assert(conshdlrdata != NULL);
16065 
16066  /* process single constraints */
16067  firstchange = INT_MAX;
16068  firstupgradetry = INT_MAX;
16069  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16070  {
16071  int npresolrounds;
16072  SCIP_Bool infeasible;
16073 
16074  infeasible = FALSE;
16075 
16076  cons = conss[c];
16077  assert(SCIPconsIsActive(cons));
16078  consdata = SCIPconsGetData(cons);
16079  assert(consdata != NULL);
16080 
16081  if( consdata->eventdata == NULL )
16082  {
16083  /* catch bound change events of variables */
16084  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16085  assert(consdata->eventdata != NULL);
16086  }
16087 
16088  /* constraint should not be already presolved in the initial round */
16089  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16090  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16091  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16092  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16093 
16094  /* incorporate fixings and aggregations in constraint */
16095  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16096 
16097  if( infeasible )
16098  {
16099  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16100  cutoff = TRUE;
16101  break;
16102  }
16103 
16104  assert(consdata->removedfixings);
16105 
16106  /* we can only presolve linear constraints, that are not modifiable */
16107  if( SCIPconsIsModifiable(cons) )
16108  continue;
16109 
16110  /* remember the first changed constraint to begin the next aggregation round with */
16111  if( firstchange == INT_MAX && consdata->changed )
16112  firstchange = c;
16113 
16114  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16115  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16116  firstupgradetry = c;
16117 
16118  /* check, if constraint is already preprocessed */
16119  if( consdata->presolved )
16120  continue;
16121 
16122  assert(SCIPconsIsActive(cons));
16123 
16124  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16125  SCIPdebugPrintCons(scip, cons, NULL);
16126 
16127  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16128  * to avoid nearly infinite cycling due to very small bound changes)
16129  */
16130  npresolrounds = 0;
16131  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16132  {
16133  assert(!cutoff);
16134  npresolrounds++;
16135 
16136  /* mark constraint being presolved and propagated */
16137  consdata->presolved = TRUE;
16138  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16139 
16140  /* normalize constraint */
16141  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16142 
16143  if( infeasible )
16144  {
16145  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16146  cutoff = TRUE;
16147  break;
16148  }
16149 
16150  /* tighten left and right hand side due to integrality */
16151  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16152 
16153  if( infeasible )
16154  {
16155  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16156  cutoff = TRUE;
16157  break;
16158  }
16159 
16160  /* check bounds */
16161  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16162  {
16163  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16164  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16165  cutoff = TRUE;
16166  break;
16167  }
16168 
16169  /* tighten variable's bounds */
16170  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16171  if( cutoff )
16172  break;
16173 
16174  /* check for fixed variables */
16175  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16176  if( cutoff )
16177  break;
16178 
16179  /* check constraint for infeasibility and redundancy */
16180  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
16181  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16182  {
16183  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16184  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16185  cutoff = TRUE;
16186  break;
16187  }
16188  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16189  {
16190  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16191  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16192  SCIP_CALL( SCIPdelCons(scip, cons) );
16193  assert(!SCIPconsIsActive(cons));
16194 
16195  if( !consdata->upgraded )
16196  (*ndelconss)++;
16197  break;
16198  }
16199  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
16200  {
16201  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16202  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16203  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16204  if( !consdata->upgraded )
16205  (*nchgsides)++;
16206  }
16207  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16208  {
16209  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16210  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16211  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16212  if( !consdata->upgraded )
16213  (*nchgsides)++;
16214  }
16215  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
16216 
16217  /* handle empty constraint */
16218  if( consdata->nvars == 0 )
16219  {
16220  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16221  {
16222  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16223  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16224  cutoff = TRUE;
16225  }
16226  else
16227  {
16228  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16229  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16230  SCIP_CALL( SCIPdelCons(scip, cons) );
16231  assert(!SCIPconsIsActive(cons));
16232 
16233  if( !consdata->upgraded )
16234  (*ndelconss)++;
16235  }
16236  break;
16237  }
16238 
16239  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16240  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16241 
16242  /* try to simplify inequalities */
16243  if( conshdlrdata->simplifyinequalities )
16244  {
16245  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16246 
16247  if( cutoff )
16248  break;
16249  }
16250 
16251  /* aggregation variable in equations */
16252  if( conshdlrdata->aggregatevariables )
16253  {
16254  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16255  if( cutoff )
16256  break;
16257  }
16258  }
16259 
16260  if( !cutoff && !SCIPisStopped(scip) )
16261  {
16262  /* perform ranged row propagation */
16263  if( conshdlrdata->rangedrowpropagation )
16264  {
16265  int lastnfixedvars;
16266 
16267  lastnfixedvars = *nfixedvars;
16268 
16269  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16270  if( !cutoff )
16271  {
16272  if( lastnfixedvars < *nfixedvars )
16273  {
16274  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16275  }
16276  }
16277  }
16278 
16279  /* extract cliques from constraint */
16280  if( !cutoff && SCIPconsIsActive(cons) )
16281  {
16282  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16283  nfixedvars, nchgbds, &cutoff) );
16284 
16285  /* check if the constraint got redundant or infeasible */
16286  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16287  {
16288  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16289  {
16290  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16291  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16292  cutoff = TRUE;
16293  }
16294  else
16295  {
16296  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16297  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16298  SCIP_CALL( SCIPdelCons(scip, cons) );
16299  assert(!SCIPconsIsActive(cons));
16300 
16301  if( !consdata->upgraded )
16302  (*ndelconss)++;
16303  }
16304  }
16305  }
16306 
16307  /* convert special equalities */
16308  if( !cutoff && SCIPconsIsActive(cons) )
16309  {
16310  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16311  }
16312 
16313  /* apply dual presolving for variables that appear in only one constraint */
16314  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
16315  {
16316  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16317  }
16318 
16319  /* check if an inequality is parallel to the objective function */
16320  if( !cutoff && SCIPconsIsActive(cons) )
16321  {
16322  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16323  }
16324 
16325  /* remember the first changed constraint to begin the next aggregation round with */
16326  if( firstchange == INT_MAX && consdata->changed )
16327  firstchange = c;
16328 
16329  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16330  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16331  firstupgradetry = c;
16332  }
16333 
16334  /* singleton column stuffing */
16335  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16336  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowDualReds(scip) )
16337  {
16338  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16339  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16340 
16341  /* handle empty constraint */
16342  if( consdata->nvars == 0 )
16343  {
16344  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16345  {
16346  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16347  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16348  cutoff = TRUE;
16349  }
16350  else
16351  {
16352  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16353  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16354  SCIP_CALL( SCIPdelCons(scip, cons) );
16355  assert(!SCIPconsIsActive(cons));
16356 
16357  if( !consdata->upgraded )
16358  (*ndelconss)++;
16359  }
16360  break;
16361  }
16362  }
16363  }
16364 
16365  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16366  * only apply this expensive procedure in exhaustive presolving timing
16367  */
16368  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16369  {
16370  assert(firstchange >= 0);
16371 
16372  if( firstchange < nconss && conshdlrdata->presolusehashing )
16373  {
16374  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16375  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16376  ndelconss, nchgsides) );
16377  }
16378 
16379  if( firstchange < nconss && conshdlrdata->presolpairwise )
16380  {
16381  SCIP_CONS** usefulconss;
16382  int nusefulconss;
16383  int firstchangenew;
16384  SCIP_Longint npaircomparisons;
16385 
16386  npaircomparisons = 0;
16387  oldndelconss = *ndelconss;
16388  oldnchgsides = *nchgsides;
16389  oldnchgcoefs = *nchgcoefs;
16390 
16391  /* allocate temporary memory */
16392  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16393 
16394  nusefulconss = 0;
16395  firstchangenew = -1;
16396  for( c = 0; c < nconss; ++c )
16397  {
16398  /* update firstchange */
16399  if( c == firstchange )
16400  firstchangenew = nusefulconss;
16401 
16402  /* ignore inactive and modifiable constraints */
16403  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16404  continue;
16405 
16406  usefulconss[nusefulconss] = conss[c];
16407  ++nusefulconss;
16408  }
16409  firstchange = firstchangenew;
16410  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16411 
16412  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16413  {
16414  /* constraint has become inactive or modifiable during pairwise presolving */
16415  if( usefulconss[c] == NULL )
16416  continue;
16417 
16418  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16419 
16420  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16421  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16422  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16423 
16424  if( npaircomparisons > conshdlrdata->nmincomparisons )
16425  {
16426  assert(npaircomparisons > 0);
16427  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16428  break;
16429  oldndelconss = *ndelconss;
16430  oldnchgsides = *nchgsides;
16431  oldnchgcoefs = *nchgcoefs;
16432  npaircomparisons = 0;
16433  }
16434  }
16435  /* free temporary memory */
16436  SCIPfreeBufferArray(scip, &usefulconss);
16437  }
16438  }
16439 
16440  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16441  * in linear constraints and we therefore have full information about it
16442  */
16443  if( !cutoff && firstupgradetry < nconss
16444  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16445  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16446  )
16447  {
16448  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) && !SCIPisStopped(scip) )
16449  {
16450  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16451  }
16452  }
16453 
16454  /* try to upgrade constraints into a more specific constraint type;
16455  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16456  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16457  */
16458  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16459  {
16460  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16461  {
16462  cons = conss[c];
16463 
16464  /* don't upgrade modifiable constraints */
16465  if( SCIPconsIsModifiable(cons) )
16466  continue;
16467 
16468  consdata = SCIPconsGetData(cons);
16469  assert(consdata != NULL);
16470 
16471  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16472  if( consdata->upgradetried )
16473  continue;
16474  /* @todo force that upgrade will be performed later? */
16475  if( !consdata->presolved )
16476  continue;
16477 
16478  consdata->upgradetried = TRUE;
16479  if( SCIPconsIsActive(cons) )
16480  {
16481  SCIP_CONS* upgdcons;
16482 
16483  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16484  if( upgdcons != NULL )
16485  {
16486  /* add the upgraded constraint to the problem */
16487  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16488  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16489  (*nupgdconss)++;
16490 
16491  /* mark the linear constraint being upgraded and to be removed after presolving;
16492  * don't delete it directly, because it may help to preprocess other linear constraints
16493  */
16494  assert(!consdata->upgraded);
16495  consdata->upgraded = TRUE;
16496 
16497  /* delete upgraded inequalities immediately;
16498  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16499  */
16500  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16501  || !conshdlrdata->presolpairwise
16502  || (conshdlrdata->maxaggrnormscale == 0.0) )
16503  {
16504  SCIP_CALL( SCIPdelCons(scip, cons) );
16505  }
16506  }
16507  }
16508  }
16509  }
16510 
16511  /* return the correct result code */
16512  if( cutoff )
16513  *result = SCIP_CUTOFF;
16514  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16515  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16516  *result = SCIP_SUCCESS;
16517  else
16518  *result = SCIP_DIDNOTFIND;
16519 
16520  return SCIP_OKAY;
16521 }
16522 
16523 
16524 /** propagation conflict resolving method of constraint handler */
16525 static
16526 SCIP_DECL_CONSRESPROP(consRespropLinear)
16527 { /*lint --e{715}*/
16528  assert(scip != NULL);
16529  assert(cons != NULL);
16530  assert(result != NULL);
16531 
16532  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16533 
16534  return SCIP_OKAY;
16535 }
16536 
16537 
16538 /** variable rounding lock method of constraint handler */
16539 static
16540 SCIP_DECL_CONSLOCK(consLockLinear)
16541 { /*lint --e{715}*/
16542  SCIP_CONSDATA* consdata;
16543  SCIP_Bool haslhs;
16544  SCIP_Bool hasrhs;
16545  int i;
16546 
16547  assert(scip != NULL);
16548  assert(cons != NULL);
16549  consdata = SCIPconsGetData(cons);
16550  assert(consdata != NULL);
16551 
16552  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16553  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16554 
16555  /* update rounding locks of every single variable */
16556  for( i = 0; i < consdata->nvars; ++i )
16557  {
16558  if( SCIPisPositive(scip, consdata->vals[i]) )
16559  {
16560  if( haslhs )
16561  {
16562  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16563  }
16564  if( hasrhs )
16565  {
16566  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16567  }
16568  }
16569  else
16570  {
16571  if( haslhs )
16572  {
16573  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16574  }
16575  if( hasrhs )
16576  {
16577  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16578  }
16579  }
16580  }
16581 
16582  return SCIP_OKAY;
16583 }
16584 
16585 
16586 /** variable deletion method of constraint handler */
16587 static
16588 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16589 {
16590  assert(scip != NULL);
16591  assert(conshdlr != NULL);
16592  assert(conss != NULL || nconss == 0);
16593 
16594  if( nconss > 0 )
16595  {
16596  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16597  }
16598 
16599  return SCIP_OKAY;
16600 }
16601 
16602 /** constraint display method of constraint handler */
16603 static
16604 SCIP_DECL_CONSPRINT(consPrintLinear)
16605 { /*lint --e{715}*/
16606  assert(scip != NULL);
16607  assert(conshdlr != NULL);
16608  assert(cons != NULL);
16609 
16610  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16611 
16612  return SCIP_OKAY;
16613 }
16614 
16615 /** constraint copying method of constraint handler */
16616 static
16617 SCIP_DECL_CONSCOPY(consCopyLinear)
16618 { /*lint --e{715}*/
16619  SCIP_VAR** sourcevars;
16620  SCIP_Real* sourcecoefs;
16621  const char* consname;
16622  int nvars;
16623 
16624  assert(scip != NULL);
16625  assert(sourcescip != NULL);
16626  assert(sourcecons != NULL);
16627 
16628  /* get variables and coefficients of the source constraint */
16629  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16630  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16631  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16632 
16633  if( name != NULL )
16634  consname = name;
16635  else
16636  consname = SCIPconsGetName(sourcecons);
16637 
16638  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16639  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16640  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16641  assert(cons != NULL || *valid == FALSE);
16642 
16643  /* @todo should also the checkabsolute flag of the constraint be copied? */
16644 
16645  return SCIP_OKAY;
16646 }
16647 
16648 /* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
16649  * except for ranged rows for which exactly two operators '<=' must be present
16650  */
16651 static
16653  const char* str, /**< null terminated input string */
16654  char** firstoperator, /**< pointer to store the string starting at the first operator */
16655  char** secondoperator, /**< pointer to store the string starting at the second operator */
16656  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16657  )
16658 {
16659  char* curr;
16660 
16661  assert(str != NULL);
16662  assert(firstoperator != NULL);
16663  assert(secondoperator != NULL);
16664 
16665  *firstoperator = NULL;
16666  *secondoperator = NULL;
16667 
16668  curr = (char*)str;
16669  *success = TRUE;
16670 
16671  /* loop over the input string to find all operators */
16672  while( *curr && *success )
16673  {
16674  SCIP_Bool found = FALSE;
16675  int increment = 1;
16676 
16677  /* try if we found a possible operator */
16678  switch( *curr )
16679  {
16680  case '<':
16681  case '=':
16682  case '>':
16683 
16684  /* check if the two characters curr[0,1] form an operator together */
16685  if( curr[1] == '=' )
16686  {
16687  found = TRUE;
16688 
16689  /* update increment to continue after this operator */
16690  increment = 2;
16691  }
16692  break;
16693  case '[':
16694  if( strncmp(curr, "[free]", 6) == 0 )
16695  {
16696  found = TRUE;
16697 
16698  /* update increment to continue after this operator */
16699  increment = 6;
16700  }
16701  break;
16702  default:
16703  break;
16704  }
16705 
16706  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16707  if( found )
16708  {
16709  if( *firstoperator == NULL )
16710  {
16711  *firstoperator = curr;
16712  }
16713  else
16714  {
16715  if( *secondoperator != NULL )
16716  {
16717  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16718  *success = FALSE;
16719  }
16720  else if( strncmp(*firstoperator, "<=", 2) != 0 )
16721  {
16722  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16723  *success = FALSE;
16724  }
16725  else if( strncmp(curr, "<=", 2) != 0 )
16726  {
16727  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16728  *success = FALSE;
16729  }
16730 
16731  *secondoperator = curr;
16732  }
16733  }
16734 
16735  curr += increment;
16736  }
16737 
16738  /* check if we did find at least one operator */
16739  if( *success )
16740  {
16741  if( *firstoperator == NULL )
16742  {
16743  SCIPerrorMessage("Could not find any operator in line %s\n", str);
16744  *success = FALSE;
16745  }
16746  }
16747 
16748  return SCIP_OKAY;
16749 }
16750 
16751 /** constraint parsing method of constraint handler */
16752 static
16753 SCIP_DECL_CONSPARSE(consParseLinear)
16754 { /*lint --e{715}*/
16755  SCIP_VAR** vars;
16756  SCIP_Real* coefs;
16757  int nvars;
16758  int coefssize;
16759  int requsize;
16760  SCIP_Real lhs;
16761  SCIP_Real rhs;
16762  char* endptr;
16763  char* firstop;
16764  char* secondop;
16765  SCIP_Bool operatorsuccess;
16766  char* lhsstrptr;
16767  char* rhsstrptr;
16768  char* varstrptr;
16769 
16770  assert(scip != NULL);
16771  assert(success != NULL);
16772  assert(str != NULL);
16773  assert(name != NULL);
16774  assert(cons != NULL);
16775 
16776  /* set left and right hand side to their default values */
16777  lhs = -SCIPinfinity(scip);
16778  rhs = SCIPinfinity(scip);
16779 
16780  (*success) = FALSE;
16781 
16782  /* return of string empty */
16783  if( !*str )
16784  return SCIP_OKAY;
16785 
16786  /* ignore whitespace */
16787  while( isspace((unsigned char)*str) )
16788  ++str;
16789 
16790  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16791  * and the special word [free]
16792  */
16793  SCIP_CALL( findOperators(str, &firstop, &secondop, &operatorsuccess) );
16794 
16795  /* if the grammar is not valid for parsing a linear constraint, return */
16796  if( ! operatorsuccess )
16797  return SCIP_OKAY;
16798 
16799  varstrptr = (char *)str;
16800  lhsstrptr = rhsstrptr = NULL;
16801  assert(firstop != NULL);
16802 
16803  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16804  switch( *firstop )
16805  {
16806  case '<':
16807  assert(firstop[1] == '=');
16808  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16809  if( secondop != NULL )
16810  {
16811  assert(secondop[0] == '<' && secondop[1] == '=');
16812  lhsstrptr = (char *)str;
16813  varstrptr = firstop + 2;
16814  rhsstrptr = secondop + 2;
16815  }
16816  else
16817  {
16818  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16819  lhsstrptr = NULL;
16820  varstrptr = (char *)str;
16821  rhsstrptr = firstop + 2;
16822  }
16823  break;
16824  case '>':
16825  assert(firstop[1] == '=');
16826  assert(secondop == NULL);
16827  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16828  lhsstrptr = firstop + 2;
16829  break;
16830  case '=':
16831  assert(firstop[1] == '=');
16832  assert(secondop == NULL);
16833  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16834  rhsstrptr = firstop + 2;
16835  lhsstrptr = firstop + 2;
16836  break;
16837  case '[':
16838  assert(strncmp(firstop, "[free]", 6) == 0);
16839  assert(secondop == NULL);
16840  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16841  break;
16842  default:
16843  /* it should not be possible that a different character appears in that position */
16844  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16845  return SCIP_READERROR;
16846  }
16847 
16848  /* parse left hand side, if necessary */
16849  if( lhsstrptr != NULL )
16850  {
16851  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16852  {
16853  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16854  return SCIP_OKAY;
16855  }
16856 
16857  /* in case of an equation, assign the left also to the right hand side */
16858  if( rhsstrptr == lhsstrptr )
16859  rhs = lhs;
16860  }
16861 
16862  /* parse right hand side, if different from left hand side */
16863  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
16864  {
16865  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
16866  {
16867  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
16868  return SCIP_OKAY;
16869  }
16870  }
16871 
16872  /* initialize buffers for storing the variables and coefficients */
16873  coefssize = 100;
16874  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
16875  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
16876 
16877  assert(varstrptr != NULL);
16878 
16879  /* parse linear sum to get variables and coefficients */
16880  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16881 
16882  if( *success && requsize > coefssize )
16883  {
16884  /* realloc buffers and try again */
16885  coefssize = requsize;
16886  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
16887  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
16888 
16889  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16890  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
16891  }
16892 
16893  if( !*success )
16894  {
16895  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
16896  }
16897  else
16898  {
16899  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
16900  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
16901  }
16902 
16903  SCIPfreeBufferArray(scip, &coefs);
16904  SCIPfreeBufferArray(scip, &vars);
16905 
16906  return SCIP_OKAY;
16907 }
16908 
16909 
16910 /** constraint method of constraint handler which returns the variables (if possible) */
16911 static
16912 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
16913 { /*lint --e{715}*/
16914  SCIP_CONSDATA* consdata;
16915 
16916  consdata = SCIPconsGetData(cons);
16917  assert(consdata != NULL);
16918 
16919  if( varssize < consdata->nvars )
16920  (*success) = FALSE;
16921  else
16922  {
16923  assert(vars != NULL);
16924 
16925  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
16926  (*success) = TRUE;
16927  }
16928 
16929  return SCIP_OKAY;
16930 }
16931 
16932 /**! [Callback for the number of variables]*/
16933 /** constraint method of constraint handler which returns the number of variables (if possible) */
16934 static
16935 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
16936 { /*lint --e{715}*/
16937  SCIP_CONSDATA* consdata;
16938 
16939  consdata = SCIPconsGetData(cons);
16940  assert(consdata != NULL);
16941 
16942  (*nvars) = consdata->nvars;
16943  (*success) = TRUE;
16944 
16945  return SCIP_OKAY;
16946 }
16947 /**! [Callback for the number of variables]*/
16948 
16949 /*
16950  * Callback methods of event handler
16951  */
16953 static
16954 SCIP_DECL_EVENTEXEC(eventExecLinear)
16955 { /*lint --e{715}*/
16956  SCIP_CONS* cons;
16957  SCIP_CONSDATA* consdata;
16958  SCIP_VAR* var;
16959  SCIP_EVENTTYPE eventtype;
16960 
16961  assert(scip != NULL);
16962  assert(eventhdlr != NULL);
16963  assert(eventdata != NULL);
16964  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
16965  assert(event != NULL);
16966 
16967  cons = eventdata->cons;
16968  assert(cons != NULL);
16969  consdata = SCIPconsGetData(cons);
16970  assert(consdata != NULL);
16972  /* we can skip events droped for deleted constraints */
16973  if( SCIPconsIsDeleted(cons) )
16974  return SCIP_OKAY;
16975 
16976  eventtype = SCIPeventGetType(event);
16977  var = SCIPeventGetVar(event);
16978 
16979  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
16980  {
16981  SCIP_Real oldbound;
16982  SCIP_Real newbound;
16983  SCIP_Real val;
16984  int varpos;
16985 
16986  varpos = eventdata->varpos;
16987  assert(0 <= varpos && varpos < consdata->nvars);
16988  oldbound = SCIPeventGetOldbound(event);
16989  newbound = SCIPeventGetNewbound(event);
16990  assert(var != NULL);
16991  assert(consdata->vars[varpos] == var);
16992  val = consdata->vals[varpos];
16993 
16994  /* we only need to update the activities if the constraint is active,
16995  * otherwise we mark them to be invalid
16996  */
16997  if( SCIPconsIsActive(cons) )
16998  {
16999  /* update the activity values */
17000  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17001  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17002  else
17003  {
17004  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17005  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17006  }
17007  }
17008  else
17009  consdataInvalidateActivities(consdata);
17010 
17011  consdata->presolved = FALSE;
17012  consdata->rangedrowpropagated = 0;
17013 
17014  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17015  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17016  {
17017  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17018 
17019  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17020  if( consdata->maxactdeltavar == var )
17021  {
17022  consdata->maxactdelta = SCIP_INVALID;
17023  consdata->maxactdeltavar = NULL;
17024  }
17025 
17026  /* check whether bound tightening might now be successful */
17027  if( consdata->boundstightened > 0)
17028  {
17029  switch( eventtype )
17030  {
17032  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17033  consdata->boundstightened = 0;
17034  break;
17036  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17037  consdata->boundstightened = 0;
17038  break;
17039  default:
17040  SCIPerrorMessage("invalid event type %d\n", eventtype);
17041  return SCIP_INVALIDDATA;
17042  }
17043  }
17044  }
17045  /* update maximal activity delta if a bound was relaxed */
17046  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17047  {
17048  SCIP_Real lb;
17049  SCIP_Real ub;
17050  SCIP_Real domain;
17051  SCIP_Real delta;
17052 
17053  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17054 
17055  lb = SCIPvarGetLbLocal(var);
17056  ub = SCIPvarGetUbLocal(var);
17057 
17058  domain = ub - lb;
17059  delta = REALABS(val) * domain;
17060 
17061  if( delta > consdata->maxactdelta )
17062  {
17063  consdata->maxactdelta = delta;
17064  consdata->maxactdeltavar = var;
17065  }
17066  }
17067  }
17068  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17069  {
17070  /* we want to remove the fixed variable */
17071  consdata->presolved = FALSE;
17072  consdata->removedfixings = FALSE;
17073  consdata->rangedrowpropagated = 0;
17074 
17075  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17076  if( consdata->maxactdeltavar == var )
17077  {
17078  consdata->maxactdelta = SCIP_INVALID;
17079  consdata->maxactdeltavar = NULL;
17080  }
17081  }
17082 
17083  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17084  {
17085  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17086  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17087  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17088  consdata->presolved = FALSE;
17089  }
17090  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17091  {
17092  SCIP_Real oldbound;
17093  SCIP_Real newbound;
17094  SCIP_Real val;
17095  int varpos;
17096 
17097  varpos = eventdata->varpos;
17098  assert(0 <= varpos && varpos < consdata->nvars);
17099  oldbound = SCIPeventGetOldbound(event);
17100  newbound = SCIPeventGetNewbound(event);
17101  assert(var != NULL);
17102  assert(consdata->vars[varpos] == var);
17103  val = consdata->vals[varpos];
17104 
17105  consdata->rangedrowpropagated = 0;
17106 
17107  /* update the activity values */
17108  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17109  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17110  else
17111  {
17112  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17113  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17114  }
17115  }
17116  else
17117  {
17118  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17119  consdata->varsdeleted = TRUE;
17120  }
17121 
17122  return SCIP_OKAY;
17123 }
17124 
17125 
17126 /*
17127  * Callback methods of conflict handler
17128  */
17129 
17130 static
17131 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17132 { /*lint --e{715}*/
17133  SCIP_VAR** vars;
17134  SCIP_Real* vals;
17135  SCIP_Real lhs;
17136  int i;
17137 
17138  assert(scip != NULL);
17139  assert(conflicthdlr != NULL);
17140  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17141  assert(bdchginfos != NULL || nbdchginfos == 0);
17142  assert(result != NULL);
17143 
17144  /* don't process already resolved conflicts */
17145  if( resolved )
17146  {
17147  *result = SCIP_DIDNOTRUN;
17148  return SCIP_OKAY;
17149  }
17150 
17151  *result = SCIP_DIDNOTFIND;
17152 
17153  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17154  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17155  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17156  lhs = 1.0;
17157  for( i = 0; i < nbdchginfos; ++i )
17158  {
17159  assert(bdchginfos != NULL);
17160 
17161  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17162 
17163  /* we can only treat binary variables */
17164  /**@todo extend linear conflict constraints to some non-binary cases */
17165  if( !SCIPvarIsBinary(vars[i]) )
17166  break;
17167 
17168  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17169  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17170  vals[i] = 1.0;
17171  else
17172  {
17173  vals[i] = -1.0;
17174  lhs -= 1.0;
17175  }
17176  }
17177 
17178  if( i == nbdchginfos )
17179  {
17180  SCIP_CONS* cons;
17181  SCIP_CONS* upgdcons;
17182  char consname[SCIP_MAXSTRLEN];
17183 
17184  /* create a constraint out of the conflict set */
17185  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17186  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17187  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17188 
17189  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17190  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17191  if( upgdcons != NULL )
17192  {
17193  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17194  cons = upgdcons;
17195  }
17196 
17197  /* add conflict to SCIP */
17198  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17199 
17200  *result = SCIP_CONSADDED;
17201  }
17202 
17203  /* free temporary memory */
17204  SCIPfreeBufferArray(scip, &vals);
17205  SCIPfreeBufferArray(scip, &vars);
17206 
17207  return SCIP_OKAY;
17208 }
17209 
17210 
17211 /*
17212  * Quadratic constraint upgrading
17213  */
17214 
17215 
17216 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
17217  */
17218 static
17219 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
17220 { /*lint --e{715}*/
17221  SCIP_CONSDATA* upgdconsdata;
17222 
17223  assert(scip != NULL);
17224  assert(cons != NULL);
17225  assert(nupgdconss != NULL);
17226  assert(upgdconss != NULL);
17227 
17228  *nupgdconss = 0;
17229 
17230  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
17231  SCIPdebugPrintCons(scip, cons, NULL);
17232 
17233  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
17234  return SCIP_OKAY;
17235  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
17236  return SCIP_OKAY;
17237 
17238  if( upgdconsssize < 1 )
17239  {
17240  /* signal that we need more memory */
17241  *nupgdconss = -1;
17242  return SCIP_OKAY;
17243  }
17244 
17245  *nupgdconss = 1;
17246  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17247  SCIPgetNLinearVarsQuadratic(scip, cons),
17248  SCIPgetLinearVarsQuadratic(scip, cons),
17249  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
17250  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
17254  SCIPconsIsStickingAtNode(cons)) );
17255 
17256  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17257  assert(upgdconsdata != NULL);
17258 
17259  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original quadratic constraint */
17260  upgdconsdata->checkabsolute = TRUE;
17261 
17262  SCIPdebugMsg(scip, "created linear constraint:\n");
17263  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17264 
17265  return SCIP_OKAY;
17266 }
17267 
17268 /** tries to upgrade a nonlinear constraint into a linear constraint */
17269 static
17270 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17271 {
17272  SCIP_CONSDATA* upgdconsdata;
17273 
17274  assert(nupgdconss != NULL);
17275  assert(upgdconss != NULL);
17276 
17277  *nupgdconss = 0;
17278 
17279  /* no interest in nonlinear constraints */
17280  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
17281  return SCIP_OKAY;
17282 
17283  /* no interest in constant constraints */
17284  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
17285  return SCIP_OKAY;
17286 
17287  if( upgdconsssize < 1 )
17288  {
17289  /* request larger upgdconss array */
17290  *nupgdconss = -1;
17291  return SCIP_OKAY;
17292  }
17293 
17294  *nupgdconss = 1;
17295  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17297  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
17301  SCIPconsIsStickingAtNode(cons)) );
17302 
17303  upgdconsdata = SCIPconsGetData(upgdconss[0]);
17304  assert(upgdconsdata != NULL);
17305 
17306  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17307  upgdconsdata->checkabsolute = TRUE;
17308 
17309  SCIPdebugMsg(scip, "created linear constraint:\n");
17310  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17311 
17312  return SCIP_OKAY;
17313 }
17314 
17315 /*
17316  * constraint specific interface methods
17317  */
17318 
17319 /** creates the handler for linear constraints and includes it in SCIP */
17321  SCIP* scip /**< SCIP data structure */
17322  )
17323 {
17324  SCIP_CONSHDLRDATA* conshdlrdata;
17325  SCIP_CONSHDLR* conshdlr;
17326  SCIP_EVENTHDLR* eventhdlr;
17327  SCIP_CONFLICTHDLR* conflicthdlr;
17328 
17329  assert(scip != NULL);
17330 
17331  /* create event handler for bound change events */
17333  eventExecLinear, NULL) );
17334 
17335  /* create conflict handler for linear constraints */
17337  conflictExecLinear, NULL) );
17338 
17339  /* create constraint handler data */
17340  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17341 
17342  /* include constraint handler */
17345  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17346  conshdlrdata) );
17347 
17348  assert(conshdlr != NULL);
17349 
17350  /* set non-fundamental callbacks via specific setter functions */
17351  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17352  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17353  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17354  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17355  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17356  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17357  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17358  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17359  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17360  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17361  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17362  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17363  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17364  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17365  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17366  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17368  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17369  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17371  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17372  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17373 
17374  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
17375  {
17376  /* include function that upgrades quadratic constraint to linear constraints */
17378  }
17379 
17380  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17381  {
17382  /* include the linear constraint upgrade in the nonlinear constraint handler */
17384  }
17385 
17386  /* add linear constraint handler parameters */
17387  SCIP_CALL( SCIPaddIntParam(scip,
17388  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17389  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17390  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17391  SCIP_CALL( SCIPaddIntParam(scip,
17392  "constraints/" CONSHDLR_NAME "/maxrounds",
17393  "maximal number of separation rounds per node (-1: unlimited)",
17394  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17395  SCIP_CALL( SCIPaddIntParam(scip,
17396  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17397  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17398  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17399  SCIP_CALL( SCIPaddIntParam(scip,
17400  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17401  "maximal number of cuts separated per separation round",
17402  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17403  SCIP_CALL( SCIPaddIntParam(scip,
17404  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17405  "maximal number of cuts separated per separation round in the root node",
17406  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17408  "constraints/" CONSHDLR_NAME "/presolpairwise",
17409  "should pairwise constraint comparison be performed in presolving?",
17410  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17412  "constraints/" CONSHDLR_NAME "/presolusehashing",
17413  "should hash table be used for detecting redundant constraints in advance",
17414  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17415  SCIP_CALL( SCIPaddIntParam(scip,
17416  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17417  "number for minimal pairwise presolve comparisons",
17418  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17420  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17421  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17422  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17424  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17425  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17426  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17428  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17429  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17430  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17432  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17433  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17434  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17436  "constraints/" CONSHDLR_NAME "/separateall",
17437  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17438  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17440  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17441  "should presolving search for aggregations in equations",
17442  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17444  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17445  "should presolving try to simplify inequalities",
17446  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17448  "constraints/" CONSHDLR_NAME "/dualpresolving",
17449  "should dual presolving steps be performed?",
17450  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17452  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17453  "should stuffing of singleton continuous variables be performed?",
17454  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17456  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17457  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17458  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17460  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17461  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17463  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17464  "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)?",
17465  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17467  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17468  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17469  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17471  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17472  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17473  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17475  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17476  "should presolving try to detect subsets of constraints parallel to the objective function?",
17477  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17479  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17480  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17481  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17483  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17484  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17485  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17486  SCIP_CALL( SCIPaddIntParam(scip,
17487  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17488  "maximum depth to apply ranged row propagation",
17489  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17490  SCIP_CALL( SCIPaddIntParam(scip,
17491  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17492  "frequency for applying ranged row propagation",
17493  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17495  "constraints/" CONSHDLR_NAME "/multaggrremove",
17496  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17497  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17498 
17499  return SCIP_OKAY;
17500 }
17501 
17502 /** includes a linear constraint update method into the linear constraint handler */
17504  SCIP* scip, /**< SCIP data structure */
17505  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17506  int priority, /**< priority of upgrading method */
17507  const char* conshdlrname /**< name of the constraint handler */
17508  )
17509 {
17510  SCIP_CONSHDLR* conshdlr;
17511  SCIP_CONSHDLRDATA* conshdlrdata;
17512  SCIP_LINCONSUPGRADE* linconsupgrade;
17513  char paramname[SCIP_MAXSTRLEN];
17514  char paramdesc[SCIP_MAXSTRLEN];
17515 
17516  assert(scip != NULL);
17517  assert(linconsupgd != NULL);
17518  assert(conshdlrname != NULL );
17519 
17520  /* find the linear constraint handler */
17521  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17522  if( conshdlr == NULL )
17523  {
17524  SCIPerrorMessage("linear constraint handler not found\n");
17525  return SCIP_PLUGINNOTFOUND;
17526  }
17527 
17528  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17529  assert(conshdlrdata != NULL);
17530 
17531  /* check if linear constraint update method already exists in constraint handler data */
17532  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17533  {
17534  /* create a linear constraint upgrade data object */
17535  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17536 
17537  /* insert linear constraint update method into constraint handler data */
17538  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17539 
17540  /* adds parameter to turn on and off the upgrading step */
17541  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17542  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17544  paramname, paramdesc,
17545  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17546  }
17547 
17548  return SCIP_OKAY;
17549 }
17550 
17551 /** creates and captures a linear constraint
17552  *
17553  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17554  */
17556  SCIP* scip, /**< SCIP data structure */
17557  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17558  const char* name, /**< name of constraint */
17559  int nvars, /**< number of nonzeros in the constraint */
17560  SCIP_VAR** vars, /**< array with variables of constraint entries */
17561  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17562  SCIP_Real lhs, /**< left hand side of constraint */
17563  SCIP_Real rhs, /**< right hand side of constraint */
17564  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17565  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17566  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17567  * Usually set to TRUE. */
17568  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17569  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17570  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17571  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17572  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17573  * Usually set to TRUE. */
17574  SCIP_Bool local, /**< is constraint only valid locally?
17575  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17576  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17577  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17578  * adds coefficients to this constraint. */
17579  SCIP_Bool dynamic, /**< is constraint subject to aging?
17580  * Usually set to FALSE. Set to TRUE for own cuts which
17581  * are separated as constraints. */
17582  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17583  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17584  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17585  * if it may be moved to a more global node?
17586  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17587  )
17588 {
17589  SCIP_CONSHDLR* conshdlr;
17590  SCIP_CONSDATA* consdata;
17591 
17592  assert(scip != NULL);
17593  assert(cons != NULL);
17594 
17595  /* find the linear constraint handler */
17596  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17597  if( conshdlr == NULL )
17598  {
17599  SCIPerrorMessage("linear constraint handler not found\n");
17600  return SCIP_PLUGINNOTFOUND;
17601  }
17602 
17603  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17604  * constraint after presolving we have to ensure that it holds active variables
17605  */
17606  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17607  {
17608  SCIP_VAR** consvars;
17609  SCIP_Real* consvals;
17610  SCIP_Real constant = 0.0;
17611  int nconsvars;
17612  int requiredsize;
17613 
17614  nconsvars = nvars;
17615  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17616  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17617 
17618  /* get active variables for new constraint */
17619  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17620 
17621  /* if space was not enough we need to resize the buffers */
17622  if( requiredsize > nconsvars )
17623  {
17624  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17625  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17626 
17627  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17628  assert(requiredsize <= nconsvars);
17629  }
17630 
17631  /* adjust sides and check that we do not subtract infinity values */
17632  if( SCIPisInfinity(scip, REALABS(constant)) )
17633  {
17634  if( constant < 0.0 )
17635  {
17636  if( SCIPisInfinity(scip, lhs) )
17637  {
17638  SCIPfreeBufferArray(scip, &consvals);
17639  SCIPfreeBufferArray(scip, &consvars);
17640 
17641  SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name);
17642 
17643  SCIPABORT();
17644  return SCIP_INVALIDDATA; /*lint !e527*/
17645  }
17646  if( SCIPisInfinity(scip, rhs) )
17647  {
17648  SCIPfreeBufferArray(scip, &consvals);
17649  SCIPfreeBufferArray(scip, &consvars);
17650 
17651  SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17652 
17653  SCIPABORT();
17654  return SCIP_INVALIDDATA; /*lint !e527*/
17655  }
17656 
17657  lhs = -SCIPinfinity(scip);
17658  rhs = -SCIPinfinity(scip);
17659  }
17660  else
17661  {
17662  if( SCIPisInfinity(scip, -lhs) )
17663  {
17664  SCIPfreeBufferArray(scip, &consvals);
17665  SCIPfreeBufferArray(scip, &consvars);
17666 
17667  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);
17668 
17669  SCIPABORT();
17670  return SCIP_INVALIDDATA; /*lint !e527*/
17671  }
17672  if( SCIPisInfinity(scip, -rhs) )
17673  {
17674  SCIPfreeBufferArray(scip, &consvals);
17675  SCIPfreeBufferArray(scip, &consvars);
17676 
17677  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);
17678 
17679  SCIPABORT();
17680  return SCIP_INVALIDDATA; /*lint !e527*/
17681  }
17682 
17683  lhs = SCIPinfinity(scip);
17684  rhs = SCIPinfinity(scip);
17685  }
17686  }
17687  else
17688  {
17689  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17690  lhs -= constant;
17691  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17692  rhs -= constant;
17693 
17694  if( SCIPisInfinity(scip, -lhs) )
17695  lhs = -SCIPinfinity(scip);
17696  else if( SCIPisInfinity(scip, lhs) )
17697  lhs = SCIPinfinity(scip);
17698 
17699  if( SCIPisInfinity(scip, rhs) )
17700  rhs = SCIPinfinity(scip);
17701  else if( SCIPisInfinity(scip, -rhs) )
17702  rhs = -SCIPinfinity(scip);
17703  }
17704 
17705  /* create constraint data */
17706  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17707  assert(consdata != NULL);
17708 
17709  SCIPfreeBufferArray(scip, &consvals);
17710  SCIPfreeBufferArray(scip, &consvars);
17711  }
17712  else
17713  {
17714  /* create constraint data */
17715  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17716  assert(consdata != NULL);
17717  }
17718 
17719  /* create constraint */
17720  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17721  local, modifiable, dynamic, removable, stickingatnode) );
17722 
17723  return SCIP_OKAY;
17724 }
17725 
17726 /** creates and captures a linear constraint
17727  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17728  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17729  *
17730  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17731  *
17732  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17733  */
17735  SCIP* scip, /**< SCIP data structure */
17736  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17737  const char* name, /**< name of constraint */
17738  int nvars, /**< number of nonzeros in the constraint */
17739  SCIP_VAR** vars, /**< array with variables of constraint entries */
17740  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17741  SCIP_Real lhs, /**< left hand side of constraint */
17742  SCIP_Real rhs /**< right hand side of constraint */
17743  )
17744 {
17745  assert(scip != NULL);
17746 
17747  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17748  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17749 
17750  return SCIP_OKAY;
17752 
17753 /** creates by copying and captures a linear constraint */
17755  SCIP* scip, /**< target SCIP data structure */
17756  SCIP_CONS** cons, /**< pointer to store the created target constraint */
17757  SCIP* sourcescip, /**< source SCIP data structure */
17758  const char* name, /**< name of constraint */
17759  int nvars, /**< number of variables in source variable array */
17760  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17761  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17762  SCIP_Real lhs, /**< left hand side of the linear constraint */
17763  SCIP_Real rhs, /**< right hand side of the linear constraint */
17764  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17765  * variables of the target SCIP */
17766  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17767  * target constraints */
17768  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17769  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17770  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17771  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17772  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17773  SCIP_Bool local, /**< is constraint only valid locally? */
17774  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17775  SCIP_Bool dynamic, /**< is constraint subject to aging? */
17776  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17777  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17778  * if it may be moved to a more global node? */
17779  SCIP_Bool global, /**< create a global or a local copy? */
17780  SCIP_Bool* valid /**< pointer to store if the copying was valid */
17781  )
17782 {
17783  SCIP_VAR** vars;
17784  SCIP_Real* coefs;
17785 
17786  SCIP_Real constant;
17787  int requiredsize;
17788  int v;
17789  SCIP_Bool success;
17790 
17791  if( SCIPisGT(scip, lhs, rhs) )
17792  {
17793  *valid = FALSE;
17794  return SCIP_OKAY;
17795  }
17796 
17797  (*valid) = TRUE;
17798 
17799  if( nvars == 0 )
17800  {
17801  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17802  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17803  return SCIP_OKAY;
17804  }
17805 
17806  /* duplicate variable array */
17807  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17808 
17809  /* duplicate coefficient array */
17810  if( sourcecoefs != NULL )
17811  {
17812  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17813  }
17814  else
17815  {
17816  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
17817  for( v = 0; v < nvars; ++v )
17818  coefs[v] = 1.0;
17819  }
17820 
17821  constant = 0.0;
17822 
17823  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17824  * the target SCIP
17825  */
17826  if( !SCIPvarIsOriginal(vars[0]) )
17827  {
17828  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
17829 
17830  if( requiredsize > nvars )
17831  {
17832  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
17833  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
17834 
17835  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
17836  assert(requiredsize <= nvars);
17837  }
17838  }
17839  else
17840  {
17841  for( v = 0; v < nvars; ++v )
17842  {
17843  assert(SCIPvarIsOriginal(vars[v]));
17844  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
17845  assert(vars[v] != NULL);
17846  }
17847  }
17848 
17849  success = TRUE;
17850  /* map variables of the source constraint to variables of the target SCIP */
17851  for( v = 0; v < nvars && success; ++v )
17852  {
17853  SCIP_VAR* var;
17854  var = vars[v];
17855 
17856  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
17857  assert(!(success) || vars[v] != NULL);
17858  }
17859 
17860  /* only create the target constraint, if all variables could be copied */
17861  if( success )
17862  {
17863  if( !SCIPisInfinity(scip, -lhs) )
17864  lhs -= constant;
17865 
17866  if( !SCIPisInfinity(scip, rhs) )
17867  rhs -= constant;
17868 
17869  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17870  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17871  }
17872  else
17873  *valid = FALSE;
17874 
17875  /* free buffer array */
17876  SCIPfreeBufferArray(scip, &coefs);
17877  SCIPfreeBufferArray(scip, &vars);
17878 
17879  return SCIP_OKAY;
17880 }
17881 
17882 /** adds coefficient to linear constraint (if it is not zero) */
17884  SCIP* scip, /**< SCIP data structure */
17885  SCIP_CONS* cons, /**< constraint data */
17886  SCIP_VAR* var, /**< variable of constraint entry */
17887  SCIP_Real val /**< coefficient of constraint entry */
17888  )
17889 {
17890  assert(scip != NULL);
17891  assert(cons != NULL);
17892  assert(var != NULL);
17893 
17894  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17895  {
17896  SCIPerrorMessage("constraint is not linear\n");
17897  return SCIP_INVALIDDATA;
17898  }
17899 
17900  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17901  * constraint after presolving we have to ensure that it holds active variables
17902  */
17903  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
17904  {
17905  SCIP_CONSDATA* consdata;
17906  SCIP_VAR** consvars;
17907  SCIP_Real* consvals;
17908  SCIP_Real constant = 0.0;
17909  SCIP_Real rhs;
17910  SCIP_Real lhs;
17911  int nconsvars;
17912  int requiredsize;
17913  int v;
17914 
17915  nconsvars = 1;
17916  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
17917  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
17918  consvars[0] = var;
17919  consvals[0] = val;
17920 
17921  /* get active variables for new constraint */
17922  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17923 
17924  /* if space was not enough we need to resize the buffers */
17925  if( requiredsize > nconsvars )
17926  {
17927  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17928  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17929 
17930  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17931  assert(requiredsize <= nconsvars);
17932  }
17933 
17934  consdata = SCIPconsGetData(cons);
17935  assert(consdata != NULL);
17936 
17937  lhs = consdata->lhs;
17938  rhs = consdata->rhs;
17939 
17940  /* adjust sides and check that we do not subtract infinity values */
17941  /* constant is infinite */
17942  if( SCIPisInfinity(scip, REALABS(constant)) )
17943  {
17944  if( constant < 0.0 )
17945  {
17946  if( SCIPisInfinity(scip, lhs) )
17947  {
17948  SCIPfreeBufferArray(scip, &consvals);
17949  SCIPfreeBufferArray(scip, &consvars);
17950 
17951  SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
17952 
17953  SCIPABORT();
17954  return SCIP_INVALIDDATA; /*lint !e527*/
17955  }
17956  if( SCIPisInfinity(scip, rhs) )
17957  {
17958  SCIPfreeBufferArray(scip, &consvals);
17959  SCIPfreeBufferArray(scip, &consvars);
17960 
17961  SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
17962 
17963  SCIPABORT();
17964  return SCIP_INVALIDDATA; /*lint !e527*/
17965  }
17966 
17967  lhs = -SCIPinfinity(scip);
17968  rhs = -SCIPinfinity(scip);
17969  }
17970  else
17971  {
17972  if( SCIPisInfinity(scip, -lhs) )
17973  {
17974  SCIPfreeBufferArray(scip, &consvals);
17975  SCIPfreeBufferArray(scip, &consvars);
17976 
17977  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));
17978 
17979  SCIPABORT();
17980  return SCIP_INVALIDDATA; /*lint !e527*/
17981  }
17982  if( SCIPisInfinity(scip, -rhs) )
17983  {
17984  SCIPfreeBufferArray(scip, &consvals);
17985  SCIPfreeBufferArray(scip, &consvars);
17986 
17987  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));
17988 
17989  SCIPABORT();
17990  return SCIP_INVALIDDATA; /*lint !e527*/
17991  }
17992 
17993  lhs = SCIPinfinity(scip);
17994  rhs = SCIPinfinity(scip);
17995  }
17996  }
17997  /* constant is not infinite */
17998  else
17999  {
18000  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18001  lhs -= constant;
18002  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18003  rhs -= constant;
18004 
18005  if( SCIPisInfinity(scip, -lhs) )
18006  lhs = -SCIPinfinity(scip);
18007  else if( SCIPisInfinity(scip, lhs) )
18008  lhs = SCIPinfinity(scip);
18009 
18010  if( SCIPisInfinity(scip, rhs) )
18011  rhs = SCIPinfinity(scip);
18012  else if( SCIPisInfinity(scip, -rhs) )
18013  rhs = -SCIPinfinity(scip);
18014  }
18015 
18016  /* add all active variables to constraint */
18017  for( v = nconsvars - 1; v >= 0; --v )
18018  {
18019  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18020  }
18021 
18022  /* update left and right hand sides */
18023  SCIP_CALL( chgLhs(scip, cons, lhs));
18024  SCIP_CALL( chgRhs(scip, cons, rhs));
18025 
18026  SCIPfreeBufferArray(scip, &consvals);
18027  SCIPfreeBufferArray(scip, &consvars);
18028  }
18029  else
18030  {
18031  SCIP_CALL( addCoef(scip, cons, var, val) );
18032  }
18033 
18034  return SCIP_OKAY;
18035 }
18036 
18037 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18038  * not yet contained in the constraint
18039  *
18040  * @note This method may only be called during problem creation stage for an original constraint and variable.
18041  *
18042  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18043  */
18045  SCIP* scip, /**< SCIP data structure */
18046  SCIP_CONS* cons, /**< constraint data */
18047  SCIP_VAR* var, /**< variable of constraint entry */
18048  SCIP_Real val /**< new coefficient of constraint entry */
18049  )
18050 {
18051  SCIP_CONSDATA* consdata;
18052  SCIP_VAR** vars;
18053  SCIP_Bool found;
18054  int i;
18055 
18056  assert(scip != NULL);
18057  assert(cons != NULL);
18058  assert(var != NULL);
18059 
18060  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18061  {
18062  SCIPerrorMessage("constraint is not linear\n");
18063  return SCIP_INVALIDDATA;
18064  }
18065 
18066  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18067  {
18068  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18069  return SCIP_INVALIDDATA;
18070  }
18071 
18072  consdata = SCIPconsGetData(cons);
18073  assert(consdata != NULL);
18074 
18075  vars = consdata->vars;
18076  found = FALSE;
18077  i = 0;
18078  while( i < consdata->nvars )
18079  {
18080  if( vars[i] == var )
18081  {
18082  if( found || SCIPisZero(scip, val) )
18083  {
18084  SCIP_CALL( delCoefPos(scip, cons, i) );
18085 
18086  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18087  i--;
18088  }
18089  else
18090  {
18091  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18092  }
18093  found = TRUE;
18094  }
18095  i++;
18096  }
18097 
18098  if( !found && !SCIPisZero(scip, val) )
18099  {
18100  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18101  }
18102 
18103  return SCIP_OKAY;
18104 }
18105 
18106 /** deletes variable from linear constraint
18107  *
18108  * @note This method may only be called during problem creation stage for an original constraint and variable.
18109  *
18110  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18111  */
18113  SCIP* scip, /**< SCIP data structure */
18114  SCIP_CONS* cons, /**< constraint data */
18115  SCIP_VAR* var /**< variable of constraint entry */
18116  )
18117 {
18118  assert(scip != NULL);
18119  assert(cons != NULL);
18120  assert(var != NULL);
18121 
18122  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18123 
18124  return SCIP_OKAY;
18125 }
18126 
18127 /** gets left hand side of linear constraint */
18129  SCIP* scip, /**< SCIP data structure */
18130  SCIP_CONS* cons /**< constraint data */
18131  )
18132 {
18133  SCIP_CONSDATA* consdata;
18134 
18135  assert(cons != NULL);
18136 
18137  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18138  {
18139  SCIPerrorMessage("constraint is not linear\n");
18140  SCIPABORT();
18141  return SCIP_INVALID; /*lint !e527*/
18142  }
18143 
18144  consdata = SCIPconsGetData(cons);
18145  assert(consdata != NULL);
18146 
18147  return consdata->lhs;
18148 }
18149 
18150 /** gets right hand side of linear constraint */
18152  SCIP* scip, /**< SCIP data structure */
18153  SCIP_CONS* cons /**< constraint data */
18154  )
18155 {
18156  SCIP_CONSDATA* consdata;
18157 
18158  assert(cons != NULL);
18159 
18160  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18161  {
18162  SCIPerrorMessage("constraint is not linear\n");
18163  SCIPABORT();
18164  return SCIP_INVALID; /*lint !e527*/
18165  }
18166 
18167  consdata = SCIPconsGetData(cons);
18168  assert(consdata != NULL);
18169 
18170  return consdata->rhs;
18171 }
18172 
18173 /** changes left hand side of linear constraint */
18175  SCIP* scip, /**< SCIP data structure */
18176  SCIP_CONS* cons, /**< constraint data */
18177  SCIP_Real lhs /**< new left hand side */
18178  )
18179 {
18180  assert(scip != NULL);
18181  assert(cons != NULL);
18182 
18183  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18184  {
18185  SCIPerrorMessage("constraint is not linear\n");
18186  return SCIP_INVALIDDATA;
18187  }
18188 
18189  SCIP_CALL( chgLhs(scip, cons, lhs) );
18190 
18191  return SCIP_OKAY;
18192 }
18193 
18194 /** changes right hand side of linear constraint */
18196  SCIP* scip, /**< SCIP data structure */
18197  SCIP_CONS* cons, /**< constraint data */
18198  SCIP_Real rhs /**< new right hand side */
18199  )
18200 {
18201  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18202  {
18203  SCIPerrorMessage("constraint is not linear\n");
18204  return SCIP_INVALIDDATA;
18205  }
18206 
18207  SCIP_CALL( chgRhs(scip, cons, rhs) );
18208 
18209  return SCIP_OKAY;
18210 }
18211 
18212 /** gets the number of variables in the linear constraint */
18213 int SCIPgetNVarsLinear(
18214  SCIP* scip, /**< SCIP data structure */
18215  SCIP_CONS* cons /**< constraint data */
18216  )
18217 {
18218  SCIP_CONSDATA* consdata;
18219 
18220  assert(cons != NULL);
18221 
18222  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18223  {
18224  SCIPerrorMessage("constraint is not linear\n");
18225  SCIPABORT();
18226  return -1; /*lint !e527*/
18227  }
18228 
18229  consdata = SCIPconsGetData(cons);
18230  assert(consdata != NULL);
18231 
18232  return consdata->nvars;
18233 }
18234 
18235 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18237  SCIP* scip, /**< SCIP data structure */
18238  SCIP_CONS* cons /**< constraint data */
18239  )
18240 {
18241  SCIP_CONSDATA* consdata;
18242 
18243  assert(cons != NULL);
18244 
18245  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18246  {
18247  SCIPerrorMessage("constraint is not linear\n");
18248  SCIPABORT();
18249  return NULL; /*lint !e527*/
18250  }
18251 
18252  consdata = SCIPconsGetData(cons);
18253  assert(consdata != NULL);
18254 
18255  return consdata->vars;
18256 }
18257 
18258 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18260  SCIP* scip, /**< SCIP data structure */
18261  SCIP_CONS* cons /**< constraint data */
18262  )
18263 {
18264  SCIP_CONSDATA* consdata;
18265 
18266  assert(cons != NULL);
18267 
18268  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18269  {
18270  SCIPerrorMessage("constraint is not linear\n");
18271  SCIPABORT();
18272  return NULL; /*lint !e527*/
18273  }
18274 
18275  consdata = SCIPconsGetData(cons);
18276  assert(consdata != NULL);
18277 
18278  return consdata->vals;
18279 }
18280 
18281 /** gets the activity of the linear constraint in the given solution
18282  *
18283  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18284  * comprises positive and negative infinity contributions
18285  */
18287  SCIP* scip, /**< SCIP data structure */
18288  SCIP_CONS* cons, /**< constraint data */
18289  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18290  )
18291 {
18292  SCIP_CONSDATA* consdata;
18293 
18294  assert(cons != NULL);
18295 
18296  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18297  {
18298  SCIPerrorMessage("constraint is not linear\n");
18299  SCIPABORT();
18300  return SCIP_INVALID; /*lint !e527*/
18301  }
18302 
18303  consdata = SCIPconsGetData(cons);
18304  assert(consdata != NULL);
18305 
18306  if( consdata->row != NULL )
18307  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18308  else
18309  return consdataGetActivity(scip, consdata, sol);
18310 }
18311 
18312 /** gets the feasibility of the linear constraint in the given solution */
18314  SCIP* scip, /**< SCIP data structure */
18315  SCIP_CONS* cons, /**< constraint data */
18316  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18317  )
18318 {
18319  SCIP_CONSDATA* consdata;
18320 
18321  assert(cons != NULL);
18322 
18323  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18324  {
18325  SCIPerrorMessage("constraint is not linear\n");
18326  SCIPABORT();
18327  return SCIP_INVALID; /*lint !e527*/
18328  }
18329 
18330  consdata = SCIPconsGetData(cons);
18331  assert(consdata != NULL);
18332 
18333  if( consdata->row != NULL )
18334  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18335  else
18336  return consdataGetFeasibility(scip, consdata, sol);
18337 }
18338 
18339 /** gets the dual solution of the linear constraint in the current LP */
18341  SCIP* scip, /**< SCIP data structure */
18342  SCIP_CONS* cons /**< constraint data */
18343  )
18344 {
18345  SCIP_CONSDATA* consdata;
18346 
18347  assert(cons != NULL);
18348  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18349 
18350  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18351  {
18352  SCIPerrorMessage("constraint is not linear\n");
18353  SCIPABORT();
18354  return SCIP_INVALID; /*lint !e527*/
18355  }
18356 
18357  consdata = SCIPconsGetData(cons);
18358  assert(consdata != NULL);
18359 
18360  if( consdata->row != NULL )
18361  return SCIProwGetDualsol(consdata->row);
18362  else
18363  return 0.0;
18364 }
18365 
18366 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18368  SCIP* scip, /**< SCIP data structure */
18369  SCIP_CONS* cons /**< constraint data */
18370  )
18371 {
18372  SCIP_CONSDATA* consdata;
18373 
18374  assert(cons != NULL);
18375  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18376 
18377  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18378  {
18379  SCIPerrorMessage("constraint is not linear\n");
18380  SCIPABORT();
18381  return SCIP_INVALID; /*lint !e527*/
18382  }
18383 
18384  consdata = SCIPconsGetData(cons);
18385  assert(consdata != NULL);
18386 
18387  if( consdata->row != NULL )
18388  return SCIProwGetDualfarkas(consdata->row);
18389  else
18390  return 0.0;
18391 }
18392 
18393 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18394  * the user must not modify the row!
18395  */
18397  SCIP* scip, /**< SCIP data structure */
18398  SCIP_CONS* cons /**< constraint data */
18399  )
18400 {
18401  SCIP_CONSDATA* consdata;
18402 
18403  assert(cons != NULL);
18404 
18405  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18406  {
18407  SCIPerrorMessage("constraint is not linear\n");
18408  SCIPABORT();
18409  return NULL; /*lint !e527*/
18410  }
18411 
18412  consdata = SCIPconsGetData(cons);
18413  assert(consdata != NULL);
18414 
18415  return consdata->row;
18416 }
18417 
18418 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18420  SCIP* scip, /**< SCIP data structure */
18421  SCIP_CONS* cons, /**< source constraint to try to convert */
18422  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18423  )
18424 {
18425  SCIP_CONSHDLR* conshdlr;
18426  SCIP_CONSHDLRDATA* conshdlrdata;
18427  SCIP_CONSDATA* consdata;
18428  SCIP_VAR* var;
18429  SCIP_Real val;
18430  SCIP_Real lb;
18431  SCIP_Real ub;
18432  SCIP_Real poscoeffsum;
18433  SCIP_Real negcoeffsum;
18434  SCIP_Bool infeasible;
18435  SCIP_Bool integral;
18436  int nposbin;
18437  int nnegbin;
18438  int nposint;
18439  int nnegint;
18440  int nposimpl;
18441  int nnegimpl;
18442  int nposimplbin;
18443  int nnegimplbin;
18444  int nposcont;
18445  int nnegcont;
18446  int ncoeffspone;
18447  int ncoeffsnone;
18448  int ncoeffspint;
18449  int ncoeffsnint;
18450  int ncoeffspfrac;
18451  int ncoeffsnfrac;
18452  int i;
18453 
18454  assert(scip != NULL);
18455  assert(cons != NULL);
18456  assert(upgdcons != NULL);
18457 
18458  *upgdcons = NULL;
18459 
18460  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18461  if( SCIPconsIsModifiable(cons) )
18462  return SCIP_OKAY;
18463 
18464  /* check for upgradability */
18465  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18466  return SCIP_OKAY;
18467 
18468  /* get the constraint handler and check, if it's really a linear constraint */
18469  conshdlr = SCIPconsGetHdlr(cons);
18470  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18471  {
18472  SCIPerrorMessage("constraint is not linear\n");
18473  return SCIP_INVALIDDATA;
18474  }
18475 
18476  /* get constraint handler data and constraint data */
18477  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18478  assert(conshdlrdata != NULL);
18479  consdata = SCIPconsGetData(cons);
18480  assert(consdata != NULL);
18481 
18482  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18483  if( consdata->upgraded )
18484  return SCIP_OKAY;
18485 
18486  /* check, if the constraint is already stored as LP row */
18487  if( consdata->row != NULL )
18488  {
18489  if( SCIProwIsInLP(consdata->row) )
18490  {
18491  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18492  return SCIP_INVALIDDATA;
18493  }
18494  else
18495  {
18496  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18497  }
18498  }
18499 
18500  /* normalize constraint */
18501  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18502 
18503  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18504  * skipped and we hope that the infeasibility gets detected later again.
18505  *
18506  * TODO: do we want to try to upgrade the constraint anyway?
18507  *
18508  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18509  * proven to be infeasible.
18510  */
18511  if( infeasible )
18512  return SCIP_OKAY;
18513 
18514  /*
18515  * calculate some statistics on linear constraint
18516  */
18517 
18518  nposbin = 0;
18519  nnegbin = 0;
18520  nposint = 0;
18521  nnegint = 0;
18522  nposimpl = 0;
18523  nnegimpl = 0;
18524  nposimplbin = 0;
18525  nnegimplbin = 0;
18526  nposcont = 0;
18527  nnegcont = 0;
18528  ncoeffspone = 0;
18529  ncoeffsnone = 0;
18530  ncoeffspint = 0;
18531  ncoeffsnint = 0;
18532  ncoeffspfrac = 0;
18533  ncoeffsnfrac = 0;
18534  integral = TRUE;
18535  poscoeffsum = 0.0;
18536  negcoeffsum = 0.0;
18537 
18538  for( i = 0; i < consdata->nvars; ++i )
18539  {
18540  var = consdata->vars[i];
18541  val = consdata->vals[i];
18542  lb = SCIPvarGetLbLocal(var);
18543  ub = SCIPvarGetUbLocal(var);
18544  assert(!SCIPisZero(scip, val));
18545 
18546  switch( SCIPvarGetType(var) )
18547  {
18548  case SCIP_VARTYPE_BINARY:
18549  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18550  integral = integral && SCIPisIntegral(scip, val);
18551  if( val >= 0.0 )
18552  nposbin++;
18553  else
18554  nnegbin++;
18555  break;
18556  case SCIP_VARTYPE_INTEGER:
18557  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18558  integral = integral && SCIPisIntegral(scip, val);
18559  if( val >= 0.0 )
18560  nposint++;
18561  else
18562  nnegint++;
18563  break;
18564  case SCIP_VARTYPE_IMPLINT:
18565  if( SCIPvarIsBinary(var) )
18566  {
18567  if( val >= 0.0 )
18568  nposimplbin++;
18569  else
18570  nnegimplbin++;
18571  }
18572  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18573  integral = integral && SCIPisIntegral(scip, val);
18574  if( val >= 0.0 )
18575  nposimpl++;
18576  else
18577  nnegimpl++;
18578  break;
18580  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18581  if( val >= 0.0 )
18582  nposcont++;
18583  else
18584  nnegcont++;
18585  break;
18586  default:
18587  SCIPerrorMessage("unknown variable type\n");
18588  return SCIP_INVALIDDATA;
18589  }
18590  if( SCIPisEQ(scip, val, 1.0) )
18591  ncoeffspone++;
18592  else if( SCIPisEQ(scip, val, -1.0) )
18593  ncoeffsnone++;
18594  else if( SCIPisIntegral(scip, val) )
18595  {
18596  if( SCIPisPositive(scip, val) )
18597  ncoeffspint++;
18598  else
18599  ncoeffsnint++;
18600  }
18601  else
18602  {
18603  if( SCIPisPositive(scip, val) )
18604  ncoeffspfrac++;
18605  else
18606  ncoeffsnfrac++;
18607  }
18608  if( SCIPisPositive(scip, val) )
18609  poscoeffsum += val;
18610  else
18611  negcoeffsum += val;
18612  }
18613 
18614  /*
18615  * call the upgrading methods
18616  */
18617 
18618  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18619  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18620  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",
18621  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18622  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18623  poscoeffsum, negcoeffsum, integral);
18624 
18625  /* try all upgrading methods in priority order in case the upgrading step is enable */
18626  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18627  {
18628  if( conshdlrdata->linconsupgrades[i]->active )
18629  {
18630  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18631  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18632  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18633  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18634  poscoeffsum, negcoeffsum, integral,
18635  upgdcons) );
18636  }
18637  }
18638 
18639 #ifdef SCIP_DEBUG
18640  if( *upgdcons != NULL )
18641  {
18642  SCIPdebugPrintCons(scip, cons, NULL);
18643  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18644  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18645  }
18646 #endif
18647 
18648  return SCIP_OKAY;
18649 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define EVENTHDLR_DESC
Definition: cons_linear.c:108
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:100
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:116
#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:4221
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1798
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1696
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:76
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:640
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:213
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6731
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1429
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
#define NULL
Definition: def.h:239
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:853
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:406
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:719
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:99
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3968
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5120
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3139
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2130
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:3176
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:131
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:412
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:119
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8335
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17135
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:663
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:89
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1994
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:99
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
#define BINWEIGHT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3160
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2265
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_Real val, SCIP_BOUNDTYPE boundtype, SCIP_Bool global, SCIP_Bool checkreliability)
Definition: cons_linear.c:1596
public methods for memory management
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:166
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1534
#define MAXSCALEDCOEF
Definition: cons_linear.c:173
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:422
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:954
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:128
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7744
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17945
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:115
#define DEFAULT_SORTVARS
Definition: cons_linear.c:125
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9393
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:5371
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17343
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:893
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
static SCIP_RETCODE findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
#define SCIP_MAXSTRLEN
Definition: def.h:260
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3233
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16930
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:385
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1826
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:822
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:7971
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2895
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:210
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17123
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1602
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1385
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:2054
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17399
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
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:755
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:172
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2283
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:509
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:117
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1442
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1538
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1251
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16909
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1297
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4184
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:160
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:1819
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:2857
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3218
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4563
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:143
#define FALSE
Definition: def.h:65
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4582
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1198
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8086
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:314
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10325
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:243
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
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:2919
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:590
#define TRUE
Definition: def.h:64
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:137
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2056
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3638
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17180
enum Proprule PROPRULE
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:121
#define SCIPstatisticMessage
Definition: pub_message.h:104
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8355
#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:7507
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:17036
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:7940
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17089
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8385
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:5236
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:122
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:297
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9132
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8435
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:171
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:138
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3140
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
enum Proprule PROPRULE
Definition: cons_linear.c:356
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:142
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:415
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5758
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4550
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16940
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:611
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:417
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:756
public methods for SCIP variables
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:824
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1529
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17169
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8345
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3205
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:686
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16889
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:203
#define SCIPdebugMsgPrint
Definition: scip_message.h:89
#define SCIPdebugMsg
Definition: scip_message.h:88
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:155
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2299
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1483
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:870
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:140
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8137
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:8845
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:279
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:118
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2224
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:5040
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:1011
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:699
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:104
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:105
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:9553
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:2014
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8375
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
public methods for querying solving statistics
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:94
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17159
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17080
#define MAXCONSPRESOLROUNDS
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4199
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:8727
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:530
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1310
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8072
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5249
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:7170
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:6819
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17353
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:111
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:110
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:8411
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:150
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1198
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:648
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8415
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:112
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:409
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5302
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:2480
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:476
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4191
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2822
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:95
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
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:3446
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8461
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3527
public methods for event handler plugins and event handlers
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax)
Definition: cons_linear.c:2579
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:5347
#define COPYSIGN
Definition: def.h:230
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1796
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1405
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:6691
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:490
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:168
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3565
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:449
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:128
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2127
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3291
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4375
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2077
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:397
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:8966
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17100
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8295
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16729
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:434
constraint handler for quadratic constraints
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4211
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5105
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2028
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3847
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:5156
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:434
#define REALABS(x)
Definition: def.h:174
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:341
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:620
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:101
public methods for problem copies
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8425
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5087
#define SCIP_CALL(x)
Definition: def.h:351
SCIP_Real SCIPgetLowerbound(SCIP *scip)
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5273
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:93
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5440
#define SCIPhashSignature64(a)
Definition: pub_misc.h:473
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:1740
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17147
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2395
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:334
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:2379
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:296
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
Definition: grphload.c:88
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8315
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4041
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:294
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:709
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:268
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:51
static SCIP_DECL_CONSTRANS(consTransLinear)
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:141
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4593
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:7597
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:2184
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:155
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4450
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1087
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16858
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2522
#define QUADCONSUPGD_PRIORITY
Definition: cons_linear.c:184
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3439
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1018
#define SCIP_Bool
Definition: def.h:62
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1519
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:102
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:96
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:995
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4125
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1378
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1336
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3071
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:715
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6999
constraint handler for nonlinear constraints
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:568
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:147
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2550
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:145
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4547
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7454
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8096
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11422
#define MIN(x, y)
Definition: def.h:209
methods for debugging
public methods for LP management
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8205
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2297
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip_lp.c:1495
public methods for cuts and aggregation rows
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8275
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2031
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17191
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1244
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:468
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17935
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2317
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:185
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17078
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip_var.c:104
static int getVarWeight(SCIP_VAR *var)
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8168
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16902
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4290
#define MAXDNOM
Definition: cons_linear.c:172
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:847
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2272
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2326
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17111
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:2045
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:116
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12253
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:5416
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
Proprule
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:114
#define SCIP_MAXTREEDEPTH
Definition: def.h:287
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2089
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:152
public methods for the LP relaxation, rows and columns
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:144
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7430
#define MINVALRECOMP
Definition: cons_linear.c:181
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:91
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2044
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8527
#define SCIP_REAL_MAX
Definition: def.h:151
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2625
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1324
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:333
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3749
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:174
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:8469
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)
#define SCIP_LONGINT_FORMAT
Definition: def.h:142
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:578
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:544
public methods for branching rule plugins and branching
SCIP_VAR ** b
Definition: circlepacking.c:56
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3185
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1474
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
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:5700
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:652
general public methods
#define MAX(x, y)
Definition: def.h:208
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5081
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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:2706
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
public methods for solutions
static const SCIP_Real scalars[]
Definition: lp.c:5650
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:737
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1724
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8106
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:5529
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:458
#define CONTWEIGHT
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:1335
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1458
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:790
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:482
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
public methods for conflict analysis handlers
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3094
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:7879
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:687
public methods for the probing mode
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1187
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip_var.c:8478
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:761
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:602
public methods for message output
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1174
SCIP_VAR * a
Definition: circlepacking.c:57
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9449
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1999
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:111
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16848
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:8277
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1217
#define SCIP_Real
Definition: def.h:150
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7003
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8325
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1628
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:739
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:59
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9507
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:146
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:916
#define EVENTHDLR_NAME
Definition: cons_linear.c:107
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:92
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:4618
public methods for message handling
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1126
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8265
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8441
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define SCIP_INVALID
Definition: def.h:170
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:163
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2094
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3693
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:90
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
#define SCIP_Longint
Definition: def.h:135
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17455
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17026
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2068
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:474
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:267
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16894
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7812
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1351
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:9563
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:50
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17409
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:117
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16871
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:388
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8285
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define MAXVALRECOMP
Definition: cons_linear.c:180
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:685
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:134
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3280
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:330
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:165
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:530
#define SCIPcombineTwoInt(a, b)
Definition: pub_misc.h:480
#define SCIPABORT()
Definition: def.h:323
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:220
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16920
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8454
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1410
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16950
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:375
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1324
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define INTWEIGHT
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:211
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4858
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8706
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
#define ABS(x)
Definition: def.h:204
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:57
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1981
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:129
int SCIPgetNSepaRounds(SCIP *scip)
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:120
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17016
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16884
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:2006
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1052
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:134
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:343
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1285
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:107
memory allocation routines
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:164
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)