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-2023 Zuse Institute Berlin (ZIB) */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 
25 /**@file cons_linear.c
26  * @ingroup DEFPLUGINS_CONS
27  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
28  * @author Tobias Achterberg
29  * @author Timo Berthold
30  * @author Marc Pfetsch
31  * @author Kati Wolter
32  * @author Michael Winkler
33  * @author Gerald Gamrath
34  * @author Domenico Salvagnin
35  *
36  * Linear constraints are separated with a high priority, because they are easy
37  * to separate. Instead of using the global cut pool, the same effect can be
38  * implemented by adding linear constraints to the root node, such that they are
39  * separated each time, the linear constraints are separated. A constraint
40  * handler, which generates linear constraints in this way should have a lower
41  * separation priority than the linear constraint handler, and it should have a
42  * separation frequency that is a multiple of the frequency of the linear
43  * constraint handler. In this way, it can be avoided to separate the same cut
44  * twice, because if a separation run of the handler is always preceded by a
45  * separation of the linear constraints, the priorily added constraints are
46  * always satisfied.
47  *
48  * Linear constraints are enforced and checked with a very low priority. Checking
49  * of (many) linear constraints is much more involved than checking the solution
50  * values for integrality. Because we are separating the linear constraints quite
51  * often, it is only necessary to enforce them for integral solutions. A constraint
52  * handler which generates pool cuts in its enforcing method should have an
53  * enforcing priority smaller than that of the linear constraint handler to avoid
54  * regenerating constraints which already exist.
55  */
56 
57 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
58 
59 #include "blockmemshell/memory.h"
60 #include "scip/cons_nonlinear.h"
61 #include "scip/cons_knapsack.h"
62 #include "scip/cons_linear.h"
63 #include "scip/debug.h"
64 #include "scip/pub_conflict.h"
65 #include "scip/pub_cons.h"
66 #include "scip/pub_event.h"
67 #include "scip/pub_expr.h"
68 #include "scip/pub_lp.h"
69 #include "scip/pub_message.h"
70 #include "scip/pub_misc.h"
71 #include "scip/pub_misc_sort.h"
72 #include "scip/pub_var.h"
73 #include "scip/scip_branch.h"
74 #include "scip/scip_conflict.h"
75 #include "scip/scip_cons.h"
76 #include "scip/scip_copy.h"
77 #include "scip/scip_cut.h"
78 #include "scip/scip_event.h"
79 #include "scip/scip_general.h"
80 #include "scip/scip_lp.h"
81 #include "scip/scip_mem.h"
82 #include "scip/scip_message.h"
83 #include "scip/scip_numerics.h"
84 #include "scip/scip_param.h"
85 #include "scip/scip_prob.h"
86 #include "scip/scip_probing.h"
87 #include "scip/scip_sol.h"
88 #include "scip/scip_solvingstats.h"
89 #include "scip/scip_tree.h"
90 #include "scip/scip_var.h"
91 #include "scip/dbldblarith.h"
92 
93 
94 #define CONSHDLR_NAME "linear"
95 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
96 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
97 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
98 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
99 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
100 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
101 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
102  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
103 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
104 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
105 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
106 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
108 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
109 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
111 #define EVENTHDLR_NAME "linear"
112 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
114 #define CONFLICTHDLR_NAME "linear"
115 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
116 #define CONFLICTHDLR_PRIORITY -1000000
118 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
119 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
120 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
121 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
122 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
123 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
124 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
125 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
126 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
127  * comparison round */
128 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
129  * propagation? */
130 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
131  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
132 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
133  * (0.0: disable constraint aggregation) */
134 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
135  * (faster, but numerically less stable) */
136 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
137  * to best node's dual bound for separating knapsack cardinality cuts */
138 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
139  * the ones with non-zero dual value? */
140 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
141 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
142 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
143 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
144 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
145  * constraints using the cheapest variable? */
146 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
147  * function defining an upper bound and prevent these constraints from
148  * entering the LP */
149 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
150  * function defining a lower bound and prevent these constraints from
151  * entering the LP */
152 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
153  * objective function */
154 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
155 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
156 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
157 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
158 
159 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
160  * removed afterwards? */
161 #define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
162 #define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
163 #define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */
164 
165 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
166 #define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */
167 #define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral
168  * type
169  */
170 #define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that
171  * redundancy-based simplifications are allowed to be applied
172  */
174 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
175 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
178 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */
179 
180 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
181  * maybe in fullDualPresolve(), see convertLongEquality()
182  */
183 
184 
185 /** constraint data for linear constraints */
186 struct SCIP_ConsData
187 {
188  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
189  SCIP_Real rhs; /**< right hand side of row */
190  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
191  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
192  QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's
193  * activity, ignoring the coefficients contributing with infinite value */
194  QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's
195  * activity, ignoring the coefficients contributing with infinite value */
196  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
197  * over all contributing values */
198  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
199  * over all contributing values */
200  QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's
201  * activity, ignoring the coefficients contributing with infinite value */
202  QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's
203  * activity, ignoring the coefficients contributing with infinite value */
204  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
205  * over all contributing values */
206  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
207  * over all contributing values */
208  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
209  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
210  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
211  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
212  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
213  SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
214  SCIP_VAR** vars; /**< variables of constraint entries */
215  SCIP_Real* vals; /**< coefficients of constraint entries */
216  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
217  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
218  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
219  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
220  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
221  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
222  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
223  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
224  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
225  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
226  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
227  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
228  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
229  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
230  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
231  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
232  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
233  int varssize; /**< size of the vars- and vals-arrays */
234  int nvars; /**< number of nonzeros in constraint */
235  int nbinvars; /**< the number of binary variables in the constraint, only valid after
236  * sorting in stage >= SCIP_STAGE_INITSOLVE
237  */
238  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
239  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
240  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
241  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
242  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
243  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
244  unsigned int validminact:1; /**< is the local minactivity valid? */
245  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
246  unsigned int validglbminact:1; /**< is the global minactivity valid? */
247  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
248  unsigned int presolved:1; /**< is constraint already presolved? */
249  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
250  unsigned int validsignature:1; /**< is the bit signature valid? */
251  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
252  unsigned int normalized:1; /**< is the constraint in normalized form? */
253  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
254  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
255  unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */
256  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
257  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
258  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
259  unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */
260  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
261  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
262  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
263  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
264  unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
265 };
266 
267 /** event data for bound change event */
268 struct SCIP_EventData
269 {
270  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
271  int varpos; /**< position of variable in vars array */
272  int filterpos; /**< position of event in variable's event filter */
273 };
274 
275 /** constraint handler data */
276 struct SCIP_ConshdlrData
277 {
278  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
279  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
280  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
281  * (0.0: disable constraint aggregation) */
282  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
283  * to best node's dual bound for separating knapsack cardinality cuts */
284  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
285  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
286  * (faster, but numerically less stable) */
287  int linconsupgradessize;/**< size of linconsupgrade array */
288  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
289  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
290  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
291  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
292  int maxsepacuts; /**< maximal number of cuts separated per separation round */
293  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
294  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
295  int naddconss; /**< number of added constraints */
296  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
297  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
298  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
299  * the ones with non-zero dual value? */
300  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
301  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
302  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
303  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
304  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
305  * constraints using the cheapest variable? */
306  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
307  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
308  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
309  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
310  * function defining an upper bound and prevent these constraints from
311  * entering the LP */
312  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
313  * function defining a lower bound and prevent these constraints from
314  * entering the LP */
315  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
316  * the objective function */
317  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
318  * infeasibility, and extract sub-constraints from ranged rows and
319  * equations */
320  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
321  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
322  int rangedrowfreq; /**< frequency for applying ranged row propagation */
323  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
324  * removed afterwards? */
325  SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
326  SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
327  SCIP_Bool extractcliques; /**< should cliques be extracted? */
328 };
329 
330 /** linear constraint update method */
331 struct SCIP_LinConsUpgrade
332 {
333  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
334  int priority; /**< priority of upgrading method */
335  SCIP_Bool active; /**< is upgrading enabled */
336 };
337 
338 
339 /*
340  * Propagation rules
341  */
342 
343 enum Proprule
344 {
345  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
346  * variable due to the right hand side of the inequality */
347  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
348  * variable due to the left hand side of the inequality */
349  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
350  * single variable in this reanged row */
351  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
352 };
353 typedef enum Proprule PROPRULE;
355 /** inference information */
356 struct InferInfo
357 {
358  union
359  {
360  struct
361  {
362  unsigned int proprule:8; /**< propagation rule that was applied */
363  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
364  } asbits;
365  int asint; /**< inference information as a single int value */
366  } val;
367 };
368 typedef struct InferInfo INFERINFO;
369 
370 /** converts an integer into an inference information */
371 static
373  int i /**< integer to convert */
374  )
375 {
376  INFERINFO inferinfo;
377 
378  inferinfo.val.asint = i;
379 
380  return inferinfo;
381 }
382 
383 /** converts an inference information into an int */
384 static
385 int inferInfoToInt(
386  INFERINFO inferinfo /**< inference information to convert */
387  )
388 {
389  return inferinfo.val.asint;
390 }
392 /** returns the propagation rule stored in the inference information */
393 static
395  INFERINFO inferinfo /**< inference information to convert */
396  )
397 {
398  return (int) inferinfo.val.asbits.proprule;
399 }
400 
401 /** returns the position stored in the inference information */
402 static
403 int inferInfoGetPos(
404  INFERINFO inferinfo /**< inference information to convert */
405  )
406 {
407  return (int) inferinfo.val.asbits.pos;
408 }
409 
410 /** constructs an inference information out of a propagation rule and a position number */
411 static
413  PROPRULE proprule, /**< propagation rule that deduced the value */
414  int pos /**< variable position, the propagation rule was applied at */
415  )
416 {
417  INFERINFO inferinfo;
418 
419  assert(pos >= 0);
420  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
421  assert(pos < (1<<24));
423  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
424  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
425 
426  return inferinfo;
427 }
428 
429 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
430 static
432  PROPRULE proprule, /**< propagation rule that deduced the value */
433  int pos /**< variable position, the propagation rule was applied at */
434  )
435 {
436  return inferInfoToInt(getInferInfo(proprule, pos));
437 }
438 
439 
440 /*
441  * memory growing methods for dynamically allocated arrays
442  */
443 
444 /** ensures, that linconsupgrades array can store at least num entries */
445 static
447  SCIP* scip, /**< SCIP data structure */
448  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
449  int num /**< minimum number of entries to store */
450  )
451 {
452  assert(scip != NULL);
453  assert(conshdlrdata != NULL);
454  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
455 
456  if( num > conshdlrdata->linconsupgradessize )
457  {
458  int newsize;
459 
460  newsize = SCIPcalcMemGrowSize(scip, num);
461  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
462  conshdlrdata->linconsupgradessize = newsize;
463  }
464  assert(num <= conshdlrdata->linconsupgradessize);
466  return SCIP_OKAY;
467 }
468 
469 /** ensures, that vars and vals arrays can store at least num entries */
470 static
472  SCIP* scip, /**< SCIP data structure */
473  SCIP_CONSDATA* consdata, /**< linear constraint data */
474  int num /**< minimum number of entries to store */
475  )
476 {
477  assert(scip != NULL);
478  assert(consdata != NULL);
479  assert(consdata->nvars <= consdata->varssize);
480 
481  if( num > consdata->varssize )
482  {
483  int newsize;
484 
485  newsize = SCIPcalcMemGrowSize(scip, num);
486  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
487  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
488  if( consdata->eventdata != NULL )
489  {
490  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
491  }
492  consdata->varssize = newsize;
493  }
494  assert(num <= consdata->varssize);
495 
496  return SCIP_OKAY;
497 }
498 
499 
500 /*
501  * local methods for managing linear constraint update methods
502  */
503 
504 /** creates a linear constraint upgrade data object */
505 static
507  SCIP* scip, /**< SCIP data structure */
508  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
509  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
510  int priority /**< priority of upgrading method */
511  )
512 {
513  assert(scip != NULL);
514  assert(linconsupgrade != NULL);
515  assert(linconsupgd != NULL);
516 
517  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
518  (*linconsupgrade)->linconsupgd = linconsupgd;
519  (*linconsupgrade)->priority = priority;
520  (*linconsupgrade)->active = TRUE;
521 
522  return SCIP_OKAY;
523 }
524 
525 /** frees a linear constraint upgrade data object */
526 static
527 void linconsupgradeFree(
528  SCIP* scip, /**< SCIP data structure */
529  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
530  )
531 {
532  assert(scip != NULL);
533  assert(linconsupgrade != NULL);
534  assert(*linconsupgrade != NULL);
535 
536  SCIPfreeBlockMemory(scip, linconsupgrade);
537 }
538 
539 /** creates constraint handler data for linear constraint handler */
540 static
542  SCIP* scip, /**< SCIP data structure */
543  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
544  SCIP_EVENTHDLR* eventhdlr /**< event handler */
545  )
546 {
547  assert(scip != NULL);
548  assert(conshdlrdata != NULL);
549  assert(eventhdlr != NULL);
550 
551  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
552  (*conshdlrdata)->linconsupgrades = NULL;
553  (*conshdlrdata)->linconsupgradessize = 0;
554  (*conshdlrdata)->nlinconsupgrades = 0;
555  (*conshdlrdata)->naddconss = 0;
556 
557  /* set event handler for updating linear constraint activity bounds */
558  (*conshdlrdata)->eventhdlr = eventhdlr;
559 
560  return SCIP_OKAY;
561 }
562 
563 /** frees constraint handler data for linear constraint handler */
564 static
565 void conshdlrdataFree(
566  SCIP* scip, /**< SCIP data structure */
567  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
568  )
569 {
570  int i;
571 
572  assert(scip != NULL);
573  assert(conshdlrdata != NULL);
574  assert(*conshdlrdata != NULL);
575 
576  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
577  {
578  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
579  }
580  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
581 
582  SCIPfreeBlockMemory(scip, conshdlrdata);
583 }
585 /** creates a linear constraint upgrade data object */
586 static
588  SCIP* scip, /**< SCIP data structure */
589  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
590  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
591  const char* conshdlrname /**< name of the constraint handler */
592  )
593 {
594  int i;
595 
596  assert(scip != NULL);
597  assert(conshdlrdata != NULL);
598  assert(linconsupgd != NULL);
599  assert(conshdlrname != NULL);
600 
601  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
602  {
603  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
604  {
605 #ifdef SCIP_DEBUG
606  SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
607 #endif
608  return TRUE;
609  }
610  }
611 
612  return FALSE;
613 }
614 
615 /** adds a linear constraint update method to the constraint handler's data */
616 static
618  SCIP* scip, /**< SCIP data structure */
619  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
620  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
621  )
622 {
623  int i;
624 
625  assert(scip != NULL);
626  assert(conshdlrdata != NULL);
627  assert(linconsupgrade != NULL);
628 
629  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
630 
631  for( i = conshdlrdata->nlinconsupgrades;
632  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
633  {
634  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
635  }
636  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
637  conshdlrdata->linconsupgrades[i] = linconsupgrade;
638  conshdlrdata->nlinconsupgrades++;
639 
640  return SCIP_OKAY;
641 }
642 
643 /*
644  * local methods
645  */
646 
647 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
648 static
650  SCIP* scip, /**< SCIP data structure */
651  SCIP_CONS* cons, /**< linear constraint */
652  SCIP_VAR* var, /**< variable of constraint entry */
653  SCIP_Real val /**< coefficient of constraint entry */
654  )
655 {
656  SCIP_CONSDATA* consdata;
657 
658  assert(scip != NULL);
659  assert(cons != NULL);
660  assert(var != NULL);
661 
662  consdata = SCIPconsGetData(cons);
663  assert(consdata != NULL);
664  assert(!SCIPisZero(scip, val));
665 
666  if( SCIPisPositive(scip, val) )
667  {
668  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
669  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
670  }
671  else
672  {
673  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
674  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
675  }
676 
677  return SCIP_OKAY;
678 }
679 
680 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
681 static
683  SCIP* scip, /**< SCIP data structure */
684  SCIP_CONS* cons, /**< linear constraint */
685  SCIP_VAR* var, /**< variable of constraint entry */
686  SCIP_Real val /**< coefficient of constraint entry */
687  )
688 {
689  SCIP_CONSDATA* consdata;
690 
691  assert(scip != NULL);
692  assert(cons != NULL);
693  assert(var != NULL);
694 
695  consdata = SCIPconsGetData(cons);
696  assert(consdata != NULL);
697  assert(!SCIPisZero(scip, val));
698 
699  if( SCIPisPositive(scip, val) )
700  {
701  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
702  !SCIPisInfinity(scip, consdata->rhs)) );
703  }
704  else
705  {
706  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
707  !SCIPisInfinity(scip, -consdata->lhs)) );
708  }
709 
710  return SCIP_OKAY;
711 }
712 
713 /** creates event data for variable at given position, and catches events */
714 /**! [SnippetDebugAssertions] */
715 static
717  SCIP* scip, /**< SCIP data structure */
718  SCIP_CONS* cons, /**< linear constraint */
719  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
720  int pos /**< array position of variable to catch bound change events for */
721  )
722 {
723  SCIP_CONSDATA* consdata;
724  assert(scip != NULL);
725  assert(cons != NULL);
726  assert(eventhdlr != NULL);
727 
728  consdata = SCIPconsGetData(cons);
729  assert(consdata != NULL);
730 
731  assert(0 <= pos && pos < consdata->nvars);
732  assert(consdata->vars != NULL);
733  assert(consdata->vars[pos] != NULL);
734  assert(SCIPvarIsTransformed(consdata->vars[pos]));
735  assert(consdata->eventdata != NULL);
736  assert(consdata->eventdata[pos] == NULL);
737 
738  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
739  consdata->eventdata[pos]->cons = cons;
740  consdata->eventdata[pos]->varpos = pos;
741 
742  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
745  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
746 
747  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
748 
749  return SCIP_OKAY;
750 }
751 /**! [SnippetDebugAssertions] */
752 
753 /** deletes event data for variable at given position, and drops events */
754 static
756  SCIP* scip, /**< SCIP data structure */
757  SCIP_CONS* cons, /**< linear constraint */
758  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
759  int pos /**< array position of variable to catch bound change events for */
760  )
761 {
762  SCIP_CONSDATA* consdata;
763  assert(scip != NULL);
764  assert(cons != NULL);
765  assert(eventhdlr != NULL);
766 
767  consdata = SCIPconsGetData(cons);
768  assert(consdata != NULL);
769 
770  assert(0 <= pos && pos < consdata->nvars);
771  assert(consdata->vars[pos] != NULL);
772  assert(consdata->eventdata != NULL);
773  assert(consdata->eventdata[pos] != NULL);
774  assert(consdata->eventdata[pos]->cons == cons);
775  assert(consdata->eventdata[pos]->varpos == pos);
776 
777  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
780  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
781 
782  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
783 
784  return SCIP_OKAY;
785 }
786 
787 /** catches bound change events for all variables in transformed linear constraint */
788 static
790  SCIP* scip, /**< SCIP data structure */
791  SCIP_CONS* cons, /**< linear constraint */
792  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
793  )
794 {
795  SCIP_CONSDATA* consdata;
796  int i;
797 
798  assert(scip != NULL);
799  assert(cons != NULL);
800 
801  consdata = SCIPconsGetData(cons);
802  assert(consdata != NULL);
803  assert(consdata->eventdata == NULL);
804 
805  /* allocate eventdata array */
806  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
807  assert(consdata->eventdata != NULL);
808  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
809 
810  /* catch event for every single variable */
811  for( i = 0; i < consdata->nvars; ++i )
812  {
813  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
814  }
815 
816  return SCIP_OKAY;
817 }
818 
819 /** drops bound change events for all variables in transformed linear constraint */
820 static
822  SCIP* scip, /**< SCIP data structure */
823  SCIP_CONS* cons, /**< linear constraint */
824  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
825  )
826 {
827  SCIP_CONSDATA* consdata;
828  int i;
829 
830  assert(scip != NULL);
831  assert(cons != NULL);
832 
833  consdata = SCIPconsGetData(cons);
834  assert(consdata != NULL);
835  assert(consdata->eventdata != NULL);
836 
837  /* drop event of every single variable */
838  for( i = consdata->nvars - 1; i >= 0; --i )
839  {
840  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
841  }
842 
843  /* free eventdata array */
844  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
845  assert(consdata->eventdata == NULL);
846 
847  return SCIP_OKAY;
848 }
849 
850 /** creates a linear constraint data */
851 static
853  SCIP* scip, /**< SCIP data structure */
854  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
855  int nvars, /**< number of nonzeros in the constraint */
856  SCIP_VAR** vars, /**< array with variables of constraint entries */
857  SCIP_Real* vals, /**< array with coefficients of constraint entries */
858  SCIP_Real lhs, /**< left hand side of row */
859  SCIP_Real rhs /**< right hand side of row */
860  )
861 {
862  int v;
863  SCIP_Real constant;
864 
865  assert(scip != NULL);
866  assert(consdata != NULL);
867  assert(nvars == 0 || vars != NULL);
868  assert(nvars == 0 || vals != NULL);
869 
870  if( SCIPisInfinity(scip, rhs) )
871  rhs = SCIPinfinity(scip);
872  else if( SCIPisInfinity(scip, -rhs) )
873  rhs = -SCIPinfinity(scip);
874 
875  if( SCIPisInfinity(scip, -lhs) )
876  lhs = -SCIPinfinity(scip);
877  else if( SCIPisInfinity(scip, lhs) )
878  lhs = SCIPinfinity(scip);
879 
880  if( SCIPisGT(scip, lhs, rhs) )
881  {
882  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
883  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
884  }
885 
886  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
887 
888  (*consdata)->varssize = 0;
889  (*consdata)->nvars = nvars;
890  (*consdata)->hascontvar = FALSE;
891  (*consdata)->hasnonbinvar = FALSE;
892  (*consdata)->hasnonbinvalid = TRUE;
893  (*consdata)->vars = NULL;
894  (*consdata)->vals = NULL;
895 
896  constant = 0.0;
897  if( nvars > 0 )
898  {
899  int k;
900 
901  SCIP_VAR** varsbuffer;
902  SCIP_Real* valsbuffer;
903 
904  /* copy variables into temporary buffer */
905  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
906  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
907  k = 0;
908 
909  /* loop over variables and sort out fixed ones */
910  for( v = 0; v < nvars; ++v )
911  {
912  SCIP_VAR* var;
913  SCIP_Real val;
914 
915  var = vars[v];
916  val = vals[v];
917 
918  assert(var != NULL);
919  if( !SCIPisZero(scip, val) )
920  {
921  /* treat fixed variable as a constant if problem compression is enabled */
923  {
924  constant += SCIPvarGetLbGlobal(var) * val;
925  }
926  else
927  {
928  varsbuffer[k] = var;
929  valsbuffer[k] = val;
930  k++;
931 
932  /* update hascontvar and hasnonbinvar flags */
933  if( !(*consdata)->hascontvar )
934  {
935  SCIP_VARTYPE vartype = SCIPvarGetType(var);
936 
937  if( vartype != SCIP_VARTYPE_BINARY )
938  {
939  (*consdata)->hasnonbinvar = TRUE;
940 
941  if( vartype == SCIP_VARTYPE_CONTINUOUS )
942  (*consdata)->hascontvar = TRUE;
943  }
944  }
945  }
946  }
947  }
948  (*consdata)->nvars = k;
949 
950  if( k > 0 )
951  {
952  /* copy the possibly reduced buffer arrays into block */
953  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
954  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
955  (*consdata)->varssize = k;
956  }
957  /* free temporary buffer */
958  SCIPfreeBufferArray(scip, &valsbuffer);
959  SCIPfreeBufferArray(scip, &varsbuffer);
960  }
961 
962  (*consdata)->eventdata = NULL;
963 
964  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
965  if( !SCIPisZero(scip, constant) )
966  {
967  if( !SCIPisInfinity(scip, REALABS(lhs)) )
968  lhs -= constant;
969 
970  if( !SCIPisInfinity(scip, REALABS(rhs)) )
971  rhs -= constant;
972  }
973 
974  (*consdata)->row = NULL;
975  (*consdata)->nlrow = NULL;
976  (*consdata)->lhs = lhs;
977  (*consdata)->rhs = rhs;
978  (*consdata)->maxabsval = SCIP_INVALID;
979  (*consdata)->minabsval = SCIP_INVALID;
980  QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID);
981  QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID);
982  (*consdata)->lastminactivity = SCIP_INVALID;
983  (*consdata)->lastmaxactivity = SCIP_INVALID;
984  (*consdata)->maxactdelta = SCIP_INVALID;
985  (*consdata)->maxactdeltavar = NULL;
986  (*consdata)->minactivityneginf = -1;
987  (*consdata)->minactivityposinf = -1;
988  (*consdata)->maxactivityneginf = -1;
989  (*consdata)->maxactivityposinf = -1;
990  (*consdata)->minactivityneghuge = -1;
991  (*consdata)->minactivityposhuge = -1;
992  (*consdata)->maxactivityneghuge = -1;
993  (*consdata)->maxactivityposhuge = -1;
994  QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID);
995  QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID);
996  (*consdata)->lastglbminactivity = SCIP_INVALID;
997  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
998  (*consdata)->glbminactivityneginf = -1;
999  (*consdata)->glbminactivityposinf = -1;
1000  (*consdata)->glbmaxactivityneginf = -1;
1001  (*consdata)->glbmaxactivityposinf = -1;
1002  (*consdata)->glbminactivityneghuge = -1;
1003  (*consdata)->glbminactivityposhuge = -1;
1004  (*consdata)->glbmaxactivityneghuge = -1;
1005  (*consdata)->glbmaxactivityposhuge = -1;
1006  (*consdata)->possignature = 0;
1007  (*consdata)->negsignature = 0;
1008  (*consdata)->validmaxabsval = FALSE;
1009  (*consdata)->validminabsval = FALSE;
1010  (*consdata)->validactivities = FALSE;
1011  (*consdata)->validminact = FALSE;
1012  (*consdata)->validmaxact = FALSE;
1013  (*consdata)->validglbminact = FALSE;
1014  (*consdata)->validglbmaxact = FALSE;
1015  (*consdata)->boundstightened = 0;
1016  (*consdata)->presolved = FALSE;
1017  (*consdata)->removedfixings = FALSE;
1018  (*consdata)->validsignature = FALSE;
1019  (*consdata)->changed = TRUE;
1020  (*consdata)->normalized = FALSE;
1021  (*consdata)->upgradetried = FALSE;
1022  (*consdata)->upgraded = FALSE;
1023  (*consdata)->indexsorted = (nvars <= 1);
1024  (*consdata)->merged = (nvars <= 1);
1025  (*consdata)->cliquesadded = FALSE;
1026  (*consdata)->implsadded = FALSE;
1027  (*consdata)->coefsorted = FALSE;
1028  (*consdata)->nbinvars = -1;
1029  (*consdata)->varsdeleted = FALSE;
1030  (*consdata)->rangedrowpropagated = 0;
1031  (*consdata)->checkabsolute = FALSE;
1032 
1033  if( SCIPisTransformed(scip) )
1034  {
1035  /* get transformed variables */
1036  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1037  }
1038 
1039  /* capture variables */
1040  for( v = 0; v < (*consdata)->nvars; v++ )
1041  {
1042  /* likely implies a deleted variable */
1043  if( (*consdata)->vars[v] == NULL )
1044  {
1045  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1046  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1047  SCIPfreeBlockMemory(scip, consdata);
1048  return SCIP_INVALIDDATA;
1049  }
1050 
1051  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1052  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1053  }
1054 
1055  return SCIP_OKAY;
1056 }
1057 
1058 /** frees a linear constraint data */
1059 static
1061  SCIP* scip, /**< SCIP data structure */
1062  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1063  )
1064 {
1065  int v;
1066 
1067  assert(scip != NULL);
1068  assert(consdata != NULL);
1069  assert(*consdata != NULL);
1070  assert((*consdata)->varssize >= 0);
1071 
1072  /* release the row */
1073  if( (*consdata)->row != NULL )
1074  {
1075  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1076  }
1077 
1078  /* release the nlrow */
1079  if( (*consdata)->nlrow != NULL )
1080  {
1081  SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
1082  }
1083 
1084  /* release variables */
1085  for( v = 0; v < (*consdata)->nvars; v++ )
1086  {
1087  assert((*consdata)->vars[v] != NULL);
1088  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1089  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1090  }
1091 
1092  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1093  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1094  SCIPfreeBlockMemory(scip, consdata);
1095 
1096  return SCIP_OKAY;
1097 }
1098 
1099 /** prints linear constraint in CIP format to file stream */
1100 static
1102  SCIP* scip, /**< SCIP data structure */
1103  SCIP_CONSDATA* consdata, /**< linear constraint data */
1104  FILE* file /**< output file (or NULL for standard output) */
1105  )
1106 {
1107  assert(scip != NULL);
1108  assert(consdata != NULL);
1109 
1110  /* print left hand side for ranged rows */
1111  if( !SCIPisInfinity(scip, -consdata->lhs)
1112  && !SCIPisInfinity(scip, consdata->rhs)
1113  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1114  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1115 
1116  /* print coefficients and variables */
1117  if( consdata->nvars == 0 )
1118  SCIPinfoMessage(scip, file, "0");
1119  else
1120  {
1121  /* post linear sum of the linear constraint */
1122  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1123  }
1124 
1125  /* print right hand side */
1126  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1127  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1128  else if( !SCIPisInfinity(scip, consdata->rhs) )
1129  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1130  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1131  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1132  else
1133  SCIPinfoMessage(scip, file, " [free]");
1134 
1135  return SCIP_OKAY;
1136 }
1137 
1138 /** prints linear constraint and contained solution values of variables to file stream */
1139 static
1141  SCIP* scip, /**< SCIP data structure */
1142  SCIP_CONS* cons, /**< linear constraint */
1143  SCIP_SOL* sol, /**< solution to print */
1144  FILE* file /**< output file (or NULL for standard output) */
1145  )
1146 {
1147  SCIP_CONSDATA* consdata;
1148 
1149  assert(scip != NULL);
1150  assert(cons != NULL);
1151 
1152  consdata = SCIPconsGetData(cons);
1153  assert(consdata != NULL);
1154 
1156 
1157  /* print left hand side for ranged rows */
1158  if( !SCIPisInfinity(scip, -consdata->lhs)
1159  && !SCIPisInfinity(scip, consdata->rhs)
1160  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1161  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1162 
1163  /* print coefficients and variables */
1164  if( consdata->nvars == 0 )
1165  SCIPinfoMessage(scip, file, "0");
1166  else
1167  {
1168  int v;
1169 
1170  /* post linear sum of the linear constraint */
1171  for( v = 0; v < consdata->nvars; ++v )
1172  {
1173  if( consdata->vals != NULL )
1174  {
1175  if( consdata->vals[v] == 1.0 )
1176  {
1177  if( v > 0 )
1178  SCIPinfoMessage(scip, file, " +");
1179  }
1180  else if( consdata->vals[v] == -1.0 )
1181  SCIPinfoMessage(scip, file, " -");
1182  else
1183  SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1184  }
1185  else if( consdata->nvars > 0 )
1186  SCIPinfoMessage(scip, file, " +");
1187 
1188  /* print variable name */
1189  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1190 
1191  SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1192  }
1193  }
1194 
1195  /* print right hand side */
1196  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1197  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1198  else if( !SCIPisInfinity(scip, consdata->rhs) )
1199  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1200  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1201  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1202  else
1203  SCIPinfoMessage(scip, file, " [free]");
1204 
1205  SCIPinfoMessage(scip, file, ";\n");
1206 
1207  return SCIP_OKAY;
1208 }
1209 
1210 /** invalidates activity bounds, such that they are recalculated in next get */
1211 static
1213  SCIP_CONSDATA* consdata /**< linear constraint */
1214  )
1215 {
1216  assert(consdata != NULL);
1217 
1218  consdata->validactivities = FALSE;
1219  consdata->validminact = FALSE;
1220  consdata->validmaxact = FALSE;
1221  consdata->validglbminact = FALSE;
1222  consdata->validglbmaxact = FALSE;
1223  consdata->validmaxabsval = FALSE;
1224  consdata->validminabsval = FALSE;
1225  consdata->hasnonbinvalid = FALSE;
1226  QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID);
1227  QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID);
1228  consdata->lastminactivity = SCIP_INVALID;
1229  consdata->lastmaxactivity = SCIP_INVALID;
1230  consdata->maxabsval = SCIP_INVALID;
1231  consdata->minabsval = SCIP_INVALID;
1232  consdata->maxactdelta = SCIP_INVALID;
1233  consdata->maxactdeltavar = NULL;
1234  consdata->minactivityneginf = -1;
1235  consdata->minactivityposinf = -1;
1236  consdata->maxactivityneginf = -1;
1237  consdata->maxactivityposinf = -1;
1238  consdata->minactivityneghuge = -1;
1239  consdata->minactivityposhuge = -1;
1240  consdata->maxactivityneghuge = -1;
1241  consdata->maxactivityposhuge = -1;
1242  QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID);
1243  QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID);
1244  consdata->lastglbminactivity = SCIP_INVALID;
1245  consdata->lastglbmaxactivity = SCIP_INVALID;
1246  consdata->glbminactivityneginf = -1;
1247  consdata->glbminactivityposinf = -1;
1248  consdata->glbmaxactivityneginf = -1;
1249  consdata->glbmaxactivityposinf = -1;
1250  consdata->glbminactivityneghuge = -1;
1251  consdata->glbminactivityposhuge = -1;
1252  consdata->glbmaxactivityneghuge = -1;
1253  consdata->glbmaxactivityposhuge = -1;
1254 }
1255 
1256 /** compute the pseudo activity of a constraint */
1257 static
1259  SCIP* scip, /**< SCIP data structure */
1260  SCIP_CONSDATA* consdata /**< linear constraint data */
1261  )
1262 {
1263  int i;
1264  int pseudoactivityposinf;
1265  int pseudoactivityneginf;
1266  SCIP_Real pseudoactivity;
1267  SCIP_Real bound;
1268  SCIP_Real val;
1269 
1270  pseudoactivity = 0;
1271  pseudoactivityposinf = 0;
1272  pseudoactivityneginf = 0;
1273 
1274  for( i = consdata->nvars - 1; i >= 0; --i )
1275  {
1276  val = consdata->vals[i];
1277  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1278  if( SCIPisInfinity(scip, bound) )
1279  {
1280  if( val > 0.0 )
1281  pseudoactivityposinf++;
1282  else
1283  pseudoactivityneginf++;
1284  }
1285  else
1286  {
1287  if( SCIPisInfinity(scip, -bound) )
1288  {
1289  if( val > 0.0 )
1290  pseudoactivityneginf++;
1291  else
1292  pseudoactivityposinf++;
1293  }
1294  else
1295  pseudoactivity += val * bound;
1296  }
1297  }
1298 
1299  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1300  return SCIP_INVALID;
1301  else if( pseudoactivityneginf > 0 )
1302  return -SCIPinfinity(scip);
1303  else if( pseudoactivityposinf > 0 )
1304  return SCIPinfinity(scip);
1305 
1306  return pseudoactivity;
1307 }
1308 
1309 /** recompute the minactivity of a constraint */
1310 static
1312  SCIP* scip, /**< SCIP data structure */
1313  SCIP_CONSDATA* consdata /**< linear constraint data */
1314  )
1315 {
1316  int i;
1317  SCIP_Real bound;
1318 
1319  QUAD_ASSIGN(consdata->minactivity, 0.0);
1320 
1321  for( i = consdata->nvars - 1; i >= 0; --i )
1322  {
1323  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1324  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1325  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1326  SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound);
1327  }
1328 
1329  /* the activity was just computed from scratch and is valid now */
1330  consdata->validminact = TRUE;
1331 
1332  /* the activity was just computed from scratch, mark it to be reliable */
1333  consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
1334 }
1335 
1336 /** recompute the maxactivity of a constraint */
1337 static
1339  SCIP* scip, /**< SCIP data structure */
1340  SCIP_CONSDATA* consdata /**< linear constraint data */
1341  )
1342 {
1343  int i;
1344  SCIP_Real bound;
1345 
1346  QUAD_ASSIGN(consdata->maxactivity, 0.0);
1347 
1348  for( i = consdata->nvars - 1; i >= 0; --i )
1349  {
1350  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1351  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1352  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1353  SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound);
1354  }
1355 
1356  /* the activity was just computed from scratch and is valid now */
1357  consdata->validmaxact = TRUE;
1358 
1359  /* the activity was just computed from scratch, mark it to be reliable */
1360  consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
1361 }
1362 
1363 /** recompute the global minactivity of a constraint */
1364 static
1366  SCIP* scip, /**< SCIP data structure */
1367  SCIP_CONSDATA* consdata /**< linear constraint data */
1368  )
1369 {
1370  int i;
1371  SCIP_Real bound;
1372 
1373  QUAD_ASSIGN(consdata->glbminactivity, 0.0);
1374 
1375  for( i = consdata->nvars - 1; i >= 0; --i )
1376  {
1377  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1378  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1379  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1380  SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound);
1381  }
1382 
1383  /* the activity was just computed from scratch and is valid now */
1384  consdata->validglbminact = TRUE;
1385 
1386  /* the activity was just computed from scratch, mark it to be reliable */
1387  consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
1388 }
1389 
1390 /** recompute the global maxactivity of a constraint */
1391 static
1393  SCIP* scip, /**< SCIP data structure */
1394  SCIP_CONSDATA* consdata /**< linear constraint data */
1395  )
1396 {
1397  int i;
1398  SCIP_Real bound;
1399 
1400  QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
1401 
1402  for( i = consdata->nvars - 1; i >= 0; --i )
1403  {
1404  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1405  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1406  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1407  SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound);
1408  }
1409 
1410  /* the activity was just computed from scratch and is valid now */
1411  consdata->validglbmaxact = TRUE;
1412 
1413  /* the activity was just computed from scratch, mark it to be reliable */
1414  consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
1415 }
1416 
1417 /** calculates maximum absolute value of coefficients */
1418 static
1420  SCIP_CONSDATA* consdata /**< linear constraint data */
1421  )
1422 {
1423  SCIP_Real absval;
1424  int i;
1425 
1426  assert(consdata != NULL);
1427  assert(!consdata->validmaxabsval);
1428  assert(consdata->maxabsval >= SCIP_INVALID);
1429 
1430  consdata->validmaxabsval = TRUE;
1431  consdata->maxabsval = 0.0;
1432  for( i = 0; i < consdata->nvars; ++i )
1433  {
1434  absval = consdata->vals[i];
1435  absval = REALABS(absval);
1436  if( absval > consdata->maxabsval )
1437  consdata->maxabsval = absval;
1438  }
1439 }
1440 
1441 /** calculates minimum absolute value of coefficients */
1442 static
1444  SCIP_CONSDATA* consdata /**< linear constraint data */
1445  )
1446 {
1447  SCIP_Real absval;
1448  int i;
1449 
1450  assert(consdata != NULL);
1451  assert(!consdata->validminabsval);
1452  assert(consdata->minabsval >= SCIP_INVALID);
1453 
1454  consdata->validminabsval = TRUE;
1455 
1456  if( consdata->nvars > 0 )
1457  consdata->minabsval = REALABS(consdata->vals[0]);
1458  else
1459  consdata->minabsval = 0.0;
1460 
1461  for( i = 1; i < consdata->nvars; ++i )
1462  {
1463  absval = consdata->vals[i];
1464  absval = REALABS(absval);
1465  if( absval < consdata->minabsval )
1466  consdata->minabsval = absval;
1467  }
1468 }
1469 
1470 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1471 static
1473  SCIP_CONSDATA* consdata /**< linear constraint data */
1474  )
1475 {
1476  int v;
1477 
1478  assert(!consdata->hasnonbinvalid);
1479  consdata->hasnonbinvar = FALSE;
1480  consdata->hascontvar = FALSE;
1481 
1482  for( v = consdata->nvars - 1; v >= 0; --v )
1483  {
1484  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1485 
1486  if( vartype != SCIP_VARTYPE_BINARY )
1487  {
1488  consdata->hasnonbinvar = TRUE;
1489 
1490  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1491  {
1492  consdata->hascontvar = TRUE;
1493  break;
1494  }
1495  }
1496  }
1497  assert(consdata->hascontvar || v < 0);
1498 
1499  consdata->hasnonbinvalid = TRUE;
1500 }
1501 
1502 
1503 #ifdef CHECKMAXACTDELTA
1504 /** checks that the stored maximal activity delta (if not invalid) is correct */
1505 static
1507  SCIP* scip, /**< SCIP data structure */
1508  SCIP_CONSDATA* consdata /**< linear constraint data */
1509  )
1510 {
1511  if( consdata->maxactdelta != SCIP_INVALID )
1512  {
1513  SCIP_Real maxactdelta = 0.0;
1514  SCIP_Real domain;
1515  SCIP_Real delta;
1516  SCIP_Real lb;
1517  SCIP_Real ub;
1518  int v;
1519 
1520  for( v = consdata->nvars - 1; v >= 0; --v )
1521  {
1522  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1523  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1524 
1525  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1526  {
1527  maxactdelta = SCIPinfinity(scip);
1528  break;
1529  }
1530 
1531  domain = ub - lb;
1532  delta = REALABS(consdata->vals[v]) * domain;
1533 
1534  if( delta > maxactdelta )
1535  {
1536  maxactdelta = delta;
1537  }
1538  }
1539  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1540  }
1541 }
1542 #else
1543 #define checkMaxActivityDelta(scip, consdata) /**/
1544 #endif
1545 
1546 /** recompute maximal activity contribution for a single variable */
1547 static
1549  SCIP* scip, /**< SCIP data structure */
1550  SCIP_CONSDATA* consdata /**< linear constraint data */
1551  )
1552 {
1553  SCIP_Real delta;
1554  int v;
1555 
1556  consdata->maxactdelta = 0.0;
1557 
1558  if( !consdata->hasnonbinvalid )
1559  consdataCheckNonbinvar(consdata);
1560 
1561  /* easy case, the problem consists only of binary variables */
1562  if( !consdata->hasnonbinvar )
1563  {
1564  for( v = consdata->nvars - 1; v >= 0; --v )
1565  {
1566  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1567  {
1568  delta = REALABS(consdata->vals[v]);
1569 
1570  if( delta > consdata->maxactdelta )
1571  {
1572  consdata->maxactdelta = delta;
1573  consdata->maxactdeltavar = consdata->vars[v];
1574  }
1575  }
1576  }
1577  return;
1578  }
1579 
1580  for( v = consdata->nvars - 1; v >= 0; --v )
1581  {
1582  SCIP_Real domain;
1583  SCIP_Real lb;
1584  SCIP_Real ub;
1585 
1586  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1587  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1588 
1589  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1590  {
1591  consdata->maxactdelta = SCIPinfinity(scip);
1592  consdata->maxactdeltavar = consdata->vars[v];
1593  break;
1594  }
1595 
1596  domain = ub - lb;
1597  delta = REALABS(consdata->vals[v]) * domain;
1598 
1599  if( delta > consdata->maxactdelta )
1600  {
1601  consdata->maxactdelta = delta;
1602  consdata->maxactdeltavar = consdata->vars[v];
1603  }
1604  }
1605 }
1606 
1607 
1608 /** updates activities for a change in a bound */
1609 static
1611  SCIP* scip, /**< SCIP data structure */
1612  SCIP_CONSDATA* consdata, /**< linear constraint data */
1613  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1614  SCIP_Real oldbound, /**< old bound of variable */
1615  SCIP_Real newbound, /**< new bound of variable */
1616  SCIP_Real val, /**< coefficient of constraint entry */
1617  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1618  SCIP_Bool global, /**< is it a global or a local bound change? */
1619  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1620  )
1621 {
1622  QUAD_MEMBER(SCIP_Real* activity);
1623  SCIP_Real* lastactivity;
1624  int* activityposinf;
1625  int* activityneginf;
1626  int* activityposhuge;
1627  int* activityneghuge;
1628  SCIP_Real oldcontribution;
1629  SCIP_Real newcontribution;
1630  SCIP_Real delta;
1631  SCIP_Bool validact;
1632  SCIP_Bool finitenewbound;
1633  SCIP_Bool hugevalnewcont;
1634 
1635  assert(scip != NULL);
1636  assert(consdata != NULL);
1637  assert(global || (var != NULL));
1638  assert(consdata->validactivities);
1639  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
1640  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
1641  assert(consdata->lastminactivity < SCIP_INVALID);
1642  assert(consdata->lastmaxactivity < SCIP_INVALID);
1643  assert(consdata->minactivityneginf >= 0);
1644  assert(consdata->minactivityposinf >= 0);
1645  assert(consdata->maxactivityneginf >= 0);
1646  assert(consdata->maxactivityposinf >= 0);
1647  assert(consdata->minactivityneghuge >= 0);
1648  assert(consdata->minactivityposhuge >= 0);
1649  assert(consdata->maxactivityneghuge >= 0);
1650  assert(consdata->maxactivityposhuge >= 0);
1651  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
1652  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
1653  assert(consdata->lastglbminactivity < SCIP_INVALID);
1654  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1655  assert(consdata->glbminactivityneginf >= 0);
1656  assert(consdata->glbminactivityposinf >= 0);
1657  assert(consdata->glbmaxactivityneginf >= 0);
1658  assert(consdata->glbmaxactivityposinf >= 0);
1659  assert(consdata->glbminactivityneghuge >= 0);
1660  assert(consdata->glbminactivityposhuge >= 0);
1661  assert(consdata->glbmaxactivityneghuge >= 0);
1662  assert(consdata->glbmaxactivityposhuge >= 0);
1663 
1664  delta = 0.0;
1665 
1666  /* we are updating global activities */
1667  if( global )
1668  {
1669  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1670  * lower bound + pos. coef: update minactivity
1671  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1672  * upper bound + pos. coef: update maxactivity
1673  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1674  */
1675  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1676  {
1677  if( val > 0.0 )
1678  {
1679  QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1680  lastactivity = &(consdata->lastglbminactivity);
1681  activityposinf = &(consdata->glbminactivityposinf);
1682  activityneginf = &(consdata->glbminactivityneginf);
1683  activityposhuge = &(consdata->glbminactivityposhuge);
1684  activityneghuge = &(consdata->glbminactivityneghuge);
1685  validact = consdata->validglbminact;
1686  }
1687  else
1688  {
1689  QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1690  lastactivity = &(consdata->lastglbmaxactivity);
1691  activityposinf = &(consdata->glbmaxactivityneginf);
1692  activityneginf = &(consdata->glbmaxactivityposinf);
1693  activityposhuge = &(consdata->glbmaxactivityposhuge);
1694  activityneghuge = &(consdata->glbmaxactivityneghuge);
1695  validact = consdata->validglbmaxact;
1696  }
1697  }
1698  else
1699  {
1700  if( val > 0.0 )
1701  {
1702  QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity);
1703  lastactivity = &(consdata->lastglbmaxactivity);
1704  activityposinf = &(consdata->glbmaxactivityposinf);
1705  activityneginf = &(consdata->glbmaxactivityneginf);
1706  activityposhuge = &(consdata->glbmaxactivityposhuge);
1707  activityneghuge = &(consdata->glbmaxactivityneghuge);
1708  validact = consdata->validglbmaxact;
1709  }
1710  else
1711  {
1712  QUAD_ASSIGN_Q(activity, &consdata->glbminactivity);
1713  lastactivity = &(consdata->lastglbminactivity);
1714  activityposinf = &(consdata->glbminactivityneginf);
1715  activityneginf = &(consdata->glbminactivityposinf);
1716  activityposhuge = &(consdata->glbminactivityposhuge);
1717  activityneghuge = &(consdata->glbminactivityneghuge);
1718  validact = consdata->validglbminact;
1719  }
1720  }
1721  }
1722  /* we are updating local activities */
1723  else
1724  {
1725  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1726  * lower bound + pos. coef: update minactivity
1727  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1728  * upper bound + pos. coef: update maxactivity
1729  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1730  */
1731  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1732  {
1733  if( val > 0.0 )
1734  {
1735  QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1736  lastactivity = &(consdata->lastminactivity);
1737  activityposinf = &(consdata->minactivityposinf);
1738  activityneginf = &(consdata->minactivityneginf);
1739  activityposhuge = &(consdata->minactivityposhuge);
1740  activityneghuge = &(consdata->minactivityneghuge);
1741  validact = consdata->validminact;
1742  }
1743  else
1744  {
1745  QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1746  lastactivity = &(consdata->lastmaxactivity);
1747  activityposinf = &(consdata->maxactivityneginf);
1748  activityneginf = &(consdata->maxactivityposinf);
1749  activityposhuge = &(consdata->maxactivityposhuge);
1750  activityneghuge = &(consdata->maxactivityneghuge);
1751  validact = consdata->validmaxact;
1752  }
1753  }
1754  else
1755  {
1756  if( val > 0.0 )
1757  {
1758  QUAD_ASSIGN_Q(activity, &consdata->maxactivity);
1759  lastactivity = &(consdata->lastmaxactivity);
1760  activityposinf = &(consdata->maxactivityposinf);
1761  activityneginf = &(consdata->maxactivityneginf);
1762  activityposhuge = &(consdata->maxactivityposhuge);
1763  activityneghuge = &(consdata->maxactivityneghuge);
1764  validact = consdata->validmaxact;
1765  }
1766  else
1767  {
1768  QUAD_ASSIGN_Q(activity, &consdata->minactivity);
1769  lastactivity = &(consdata->lastminactivity);
1770  activityposinf = &(consdata->minactivityneginf);
1771  activityneginf = &(consdata->minactivityposinf);
1772  activityposhuge = &(consdata->minactivityposhuge);
1773  activityneghuge = &(consdata->minactivityneghuge);
1774  validact = consdata->validminact;
1775  }
1776  }
1777  }
1778 
1779  oldcontribution = val * oldbound;
1780  newcontribution = val * newbound;
1781  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1782  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1783 
1784  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1785  {
1786  /* old bound was +infinity */
1787  if( oldbound > 0.0 )
1788  {
1789  assert((*activityposinf) >= 1);
1790 
1791  /* we only have to do something if the new bound is not again +infinity */
1792  if( finitenewbound || newbound < 0.0 )
1793  {
1794  /* decrease the counter for positive infinite contributions */
1795  (*activityposinf)--;
1796 
1797  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1798  if( !finitenewbound && newbound < 0.0 )
1799  (*activityneginf)++;
1800  else if( hugevalnewcont )
1801  {
1802  /* if the contribution of this variable is too large, increase the counter for huge values */
1803  if( newcontribution > 0.0 )
1804  (*activityposhuge)++;
1805  else
1806  (*activityneghuge)++;
1807  }
1808  /* "normal case": just add the contribution to the activity */
1809  else
1810  delta = newcontribution;
1811  }
1812  }
1813  /* old bound was -infinity */
1814  else
1815  {
1816  assert(oldbound < 0.0);
1817  assert((*activityneginf) >= 1);
1818 
1819  /* we only have to do something ig the new bound is not again -infinity */
1820  if( finitenewbound || newbound > 0.0 )
1821  {
1822  /* decrease the counter for negative infinite contributions */
1823  (*activityneginf)--;
1824 
1825  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1826  if( !finitenewbound && newbound > 0.0 )
1827  (*activityposinf)++;
1828  else if( hugevalnewcont )
1829  {
1830  /* if the contribution of this variable is too large, increase the counter for huge values */
1831  if( newcontribution > 0.0 )
1832  (*activityposhuge)++;
1833  else
1834  (*activityneghuge)++;
1835  }
1836  /* "normal case": just add the contribution to the activity */
1837  else
1838  delta = newcontribution;
1839  }
1840  }
1841  }
1842  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1843  {
1844  /* old contribution was too large and positive */
1845  if( oldcontribution > 0.0 )
1846  {
1847  assert((*activityposhuge) >= 1);
1848 
1849  /* decrease the counter for huge positive contributions; it might be increased again later,
1850  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1851  */
1852  (*activityposhuge)--;
1853 
1854  if( !finitenewbound )
1855  {
1856  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1857  if( newbound > 0.0 )
1858  (*activityposinf)++;
1859  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1860  else
1861  (*activityneginf)++;
1862  }
1863  else if( hugevalnewcont )
1864  {
1865  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1866  if( newcontribution > 0.0 )
1867  (*activityposhuge)++;
1868  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1869  else
1870  (*activityneghuge)++;
1871  }
1872  /* "normal case": just add the contribution to the activity */
1873  else
1874  delta = newcontribution;
1875  }
1876  /* old contribution was too large and negative */
1877  else
1878  {
1879  assert(oldcontribution < 0.0);
1880  assert((*activityneghuge) >= 1);
1881 
1882  /* decrease the counter for huge negative contributions; it might be increased again later,
1883  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1884  */
1885  (*activityneghuge)--;
1886 
1887  if( !finitenewbound )
1888  {
1889  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1890  if( newbound > 0.0 )
1891  (*activityposinf)++;
1892  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1893  else
1894  (*activityneginf)++;
1895  }
1896  else if( hugevalnewcont )
1897  {
1898  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1899  if( newcontribution > 0.0 )
1900  (*activityposhuge)++;
1901  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1902  else
1903  (*activityneghuge)++;
1904  }
1905  /* "normal case": just add the contribution to the activity */
1906  else
1907  delta = newcontribution;
1908  }
1909  }
1910  /* old bound was finite and not too large */
1911  else
1912  {
1913  if( !finitenewbound )
1914  {
1915  /* if the new bound is +infinity, the old contribution has to be subtracted
1916  * and the counter for positive infinite contributions has to be increased
1917  */
1918  if( newbound > 0.0 )
1919  {
1920  (*activityposinf)++;
1921  delta = -oldcontribution;
1922  }
1923  /* if the new bound is -infinity, the old contribution has to be subtracted
1924  * and the counter for negative infinite contributions has to be increased
1925  */
1926  else
1927  {
1928  assert(newbound < 0.0 );
1929 
1930  (*activityneginf)++;
1931  delta = -oldcontribution;
1932  }
1933  }
1934  /* if the contribution of this variable is too large, increase the counter for huge values */
1935  else if( hugevalnewcont )
1936  {
1937  if( newcontribution > 0.0 )
1938  {
1939  (*activityposhuge)++;
1940  delta = -oldcontribution;
1941  }
1942  else
1943  {
1944  (*activityneghuge)++;
1945  delta = -oldcontribution;
1946  }
1947  }
1948  /* "normal case": just update the activity */
1949  else
1950  delta = newcontribution - oldcontribution;
1951  }
1952 
1953  /* update the activity, if the current value is valid and there was a change in the finite part */
1954  if( validact && (delta != 0.0) )
1955  {
1956  SCIP_Real curractivity;
1957 
1958  /* if the absolute value of the activity is increased, this is regarded as reliable,
1959  * otherwise, we check whether we can still trust the updated value
1960  */
1961  SCIPquadprecSumQD(*activity, *activity, delta);
1962 
1963  curractivity = QUAD_TO_DBL(*activity);
1964  assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity));
1965 
1966  if( REALABS((*lastactivity)) < REALABS(curractivity) )
1967  {
1968  (*lastactivity) = curractivity;
1969  }
1970  else
1971  {
1972  if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) )
1973  {
1974  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1975  (global ? "global " : ""), curractivity);
1976 
1977  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1978  if( global )
1979  {
1980  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1981  consdata->validglbminact = FALSE;
1982  else
1983  consdata->validglbmaxact = FALSE;
1984  }
1985  else
1986  {
1987  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1988  consdata->validminact = FALSE;
1989  else
1990  consdata->validmaxact = FALSE;
1991  }
1992  }
1993  }
1994  }
1995 }
1996 
1997 /** updates minimum and maximum activity for a change in lower bound */
1998 static
2000  SCIP* scip, /**< SCIP data structure */
2001  SCIP_CONSDATA* consdata, /**< linear constraint data */
2002  SCIP_VAR* var, /**< variable that has been changed */
2003  SCIP_Real oldlb, /**< old lower bound of variable */
2004  SCIP_Real newlb, /**< new lower bound of variable */
2005  SCIP_Real val, /**< coefficient of constraint entry */
2006  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2007  )
2008 {
2009  assert(scip != NULL);
2010  assert(consdata != NULL);
2011  assert(var != NULL);
2012 
2013  if( consdata->validactivities )
2014  {
2015  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
2016 
2017  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2018  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2019  }
2020 }
2021 
2022 /** updates minimum and maximum activity for a change in upper bound */
2023 static
2025  SCIP* scip, /**< SCIP data structure */
2026  SCIP_CONSDATA* consdata, /**< linear constraint data */
2027  SCIP_VAR* var, /**< variable that has been changed */
2028  SCIP_Real oldub, /**< old upper bound of variable */
2029  SCIP_Real newub, /**< new upper bound of variable */
2030  SCIP_Real val, /**< coefficient of constraint entry */
2031  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2032  )
2033 {
2034  assert(scip != NULL);
2035  assert(consdata != NULL);
2036  assert(var != NULL);
2037 
2038  if( consdata->validactivities )
2039  {
2040  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2041 
2042  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity)));
2043  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity)));
2044  }
2045 }
2046 
2047 /** updates minimum and maximum global activity for a change in the global lower bound */
2048 static
2050  SCIP* scip, /**< SCIP data structure */
2051  SCIP_CONSDATA* consdata, /**< linear constraint data */
2052  SCIP_Real oldlb, /**< old lower bound of variable */
2053  SCIP_Real newlb, /**< new lower bound of variable */
2054  SCIP_Real val, /**< coefficient of constraint entry */
2055  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2056  )
2057 {
2058  assert(scip != NULL);
2059  assert(consdata != NULL);
2060 
2061  if( consdata->validactivities )
2062  {
2063  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2064 
2065  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2066  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2067  }
2069 
2070 /** updates minimum and maximum global activity for a change in global upper bound */
2071 static
2073  SCIP* scip, /**< SCIP data structure */
2074  SCIP_CONSDATA* consdata, /**< linear constraint data */
2075  SCIP_Real oldub, /**< old upper bound of variable */
2076  SCIP_Real newub, /**< new upper bound of variable */
2077  SCIP_Real val, /**< coefficient of constraint entry */
2078  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2079  )
2080 {
2081  assert(scip != NULL);
2082  assert(consdata != NULL);
2083 
2084  if( consdata->validactivities )
2085  {
2086  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2087 
2088  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity)));
2089  assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity)));
2090  }
2092 
2093 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2094 static
2096  SCIP* scip, /**< SCIP data structure */
2097  SCIP_CONSDATA* consdata, /**< linear constraint data */
2098  SCIP_VAR* var, /**< variable of constraint entry */
2099  SCIP_Real val, /**< coefficient of constraint entry */
2100  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2101  )
2102 {
2103  assert(scip != NULL);
2104  assert(consdata != NULL);
2105  assert(var != NULL);
2106 
2107  /* update maximum absolute value */
2108  if( consdata->validmaxabsval )
2109  {
2110  SCIP_Real absval;
2111 
2112  assert(consdata->maxabsval < SCIP_INVALID);
2113 
2114  absval = REALABS(val);
2115  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2116  }
2117 
2118  if( consdata->validminabsval )
2119  {
2120  SCIP_Real absval;
2121 
2122  assert(consdata->minabsval < SCIP_INVALID);
2123 
2124  absval = REALABS(val);
2125  consdata->minabsval = MIN(consdata->minabsval, absval);
2126  }
2127 
2128  /* update minimal and maximal activity */
2129  if( consdata->validactivities )
2130  {
2131  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2132  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2133  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2134  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2135 
2136  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2137  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2138  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2139  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2140  }
2141 }
2142 
2143 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2144 static
2146  SCIP* scip, /**< SCIP data structure */
2147  SCIP_CONSDATA* consdata, /**< linear constraint data */
2148  SCIP_VAR* var, /**< variable of constraint entry */
2149  SCIP_Real val, /**< coefficient of constraint entry */
2150  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2151  )
2152 {
2153  assert(scip != NULL);
2154  assert(consdata != NULL);
2155  assert(var != NULL);
2156 
2157  /* invalidate maximum absolute value, if this coefficient was the maximum */
2158  if( consdata->validmaxabsval )
2159  {
2160  SCIP_Real absval;
2161 
2162  absval = REALABS(val);
2163 
2164  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2165  {
2166  consdata->validmaxabsval = FALSE;
2167  consdata->maxabsval = SCIP_INVALID;
2168  }
2169  }
2170 
2171  /* invalidate minimum absolute value, if this coefficient was the minimum */
2172  if( consdata->validminabsval )
2173  {
2174  SCIP_Real absval;
2175 
2176  absval = REALABS(val);
2177 
2178  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2179  {
2180  consdata->validminabsval = FALSE;
2181  consdata->minabsval = SCIP_INVALID;
2182  }
2183  }
2184 
2185  /* update minimal and maximal activity */
2186  if( consdata->validactivities )
2187  {
2188  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2189  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2190  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2191  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2192 
2193  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2194  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2195  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2196  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2197  }
2198 }
2199 
2200 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2201 static
2203  SCIP* scip, /**< SCIP data structure */
2204  SCIP_CONSDATA* consdata, /**< linear constraint data */
2205  SCIP_VAR* var, /**< variable of constraint entry */
2206  SCIP_Real oldval, /**< old coefficient of constraint entry */
2207  SCIP_Real newval, /**< new coefficient of constraint entry */
2208  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2209  )
2210 {
2211  assert(scip != NULL);
2212  assert(consdata != NULL);
2213  assert(var != NULL);
2214 
2215  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2216  assert(!SCIPisZero(scip, oldval));
2217 
2218  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2219  assert(!SCIPisZero(scip, newval));
2220 
2221  /* update maximum absolute value */
2222  if( consdata->validmaxabsval )
2223  {
2224  SCIP_Real absval;
2225 
2226  absval = REALABS(newval);
2227 
2228  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2229  {
2230  consdata->maxabsval = absval;
2231  }
2232  else
2233  {
2234  absval = REALABS(oldval);
2235 
2236  /* invalidate maximum absolute value */
2237  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2238  {
2239  consdata->validmaxabsval = FALSE;
2240  consdata->maxabsval = SCIP_INVALID;
2241  }
2242  }
2243  }
2244 
2245  /* update minimum absolute value */
2246  if( consdata->validminabsval )
2247  {
2248  SCIP_Real absval;
2249 
2250  absval = REALABS(newval);
2251 
2252  if( SCIPisLE(scip, absval, consdata->minabsval) )
2253  {
2254  consdata->minabsval = absval;
2255  }
2256  else
2257  {
2258  absval = REALABS(oldval);
2259 
2260  /* invalidate minimum absolute value */
2261  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2262  {
2263  consdata->validminabsval = FALSE;
2264  consdata->minabsval = SCIP_INVALID;
2265  }
2266  }
2267  }
2268 
2269  /* update maximum activity delta */
2270  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2271  {
2272  SCIP_Real domain;
2273  SCIP_Real delta;
2274 
2275  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2276  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2277 
2278  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2279  delta = REALABS(newval) * domain;
2280 
2281  if( delta > consdata->maxactdelta )
2282  {
2283  consdata->maxactdelta = delta;
2284  consdata->maxactdeltavar = var;
2285  }
2286  else
2287  {
2288  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2289  if( consdata->maxactdeltavar == var )
2290  consdata->maxactdelta = SCIP_INVALID;
2291  }
2292  }
2293 
2294  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2295  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2296  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2297 }
2298 
2299 /** returns the maximum absolute value of all coefficients in the constraint */
2300 static
2302  SCIP_CONSDATA* consdata /**< linear constraint data */
2303  )
2304 {
2305  assert(consdata != NULL);
2306 
2307  if( !consdata->validmaxabsval )
2308  consdataCalcMaxAbsval(consdata);
2309  assert(consdata->validmaxabsval);
2310  assert(consdata->maxabsval < SCIP_INVALID);
2311 
2312  return consdata->maxabsval;
2313 }
2314 
2315 /** returns the minimum absolute value of all coefficients in the constraint */
2316 static
2318  SCIP_CONSDATA* consdata /**< linear constraint data */
2319  )
2321  assert(consdata != NULL);
2322 
2323  if( !consdata->validminabsval )
2324  consdataCalcMinAbsval(consdata);
2325  assert(consdata->validminabsval);
2326  assert(consdata->minabsval < SCIP_INVALID);
2327 
2328  return consdata->minabsval;
2329 }
2330 
2331 /** calculates minimum and maximum local and global activity for constraint from scratch;
2332  * additionally recalculates maximum absolute value of coefficients
2333  */
2334 static
2336  SCIP* scip, /**< SCIP data structure */
2337  SCIP_CONSDATA* consdata /**< linear constraint data */
2338  )
2339 {
2340  int i;
2341 
2342  assert(scip != NULL);
2343  assert(consdata != NULL);
2344  assert(!consdata->validactivities);
2345  assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact);
2346  assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact);
2347  assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact);
2348  assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact);
2349 
2350  consdata->validmaxabsval = TRUE;
2351  consdata->validminabsval = TRUE;
2352  consdata->validactivities = TRUE;
2353  consdata->validminact = TRUE;
2354  consdata->validmaxact = TRUE;
2355  consdata->validglbminact = TRUE;
2356  consdata->validglbmaxact = TRUE;
2357  consdata->maxabsval = 0.0;
2358  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2359  QUAD_ASSIGN(consdata->minactivity, 0.0);
2360  QUAD_ASSIGN(consdata->maxactivity, 0.0);
2361  consdata->lastminactivity = 0.0;
2362  consdata->lastmaxactivity = 0.0;
2363  consdata->minactivityneginf = 0;
2364  consdata->minactivityposinf = 0;
2365  consdata->maxactivityneginf = 0;
2366  consdata->maxactivityposinf = 0;
2367  consdata->minactivityneghuge = 0;
2368  consdata->minactivityposhuge = 0;
2369  consdata->maxactivityneghuge = 0;
2370  consdata->maxactivityposhuge = 0;
2371  QUAD_ASSIGN(consdata->glbminactivity, 0.0);
2372  QUAD_ASSIGN(consdata->glbmaxactivity, 0.0);
2373  consdata->lastglbminactivity = 0.0;
2374  consdata->lastglbmaxactivity = 0.0;
2375  consdata->glbminactivityneginf = 0;
2376  consdata->glbminactivityposinf = 0;
2377  consdata->glbmaxactivityneginf = 0;
2378  consdata->glbmaxactivityposinf = 0;
2379  consdata->glbminactivityneghuge = 0;
2380  consdata->glbminactivityposhuge = 0;
2381  consdata->glbmaxactivityneghuge = 0;
2382  consdata->glbmaxactivityposhuge = 0;
2383 
2384  for( i = 0; i < consdata->nvars; ++i )
2385  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2386 
2387  consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity);
2388  consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity);
2389  consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity);
2390  consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2391 }
2392 
2393 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2394  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2395  */
2396 static
2397 void getMinActivity(
2398  SCIP* scip, /**< SCIP data structure */
2399  SCIP_CONSDATA* consdata, /**< linear constraint */
2400  int posinf, /**< number of coefficients contributing pos. infinite value */
2401  int neginf, /**< number of coefficients contributing neg. infinite value */
2402  int poshuge, /**< number of coefficients contributing huge pos. value */
2403  int neghuge, /**< number of coefficients contributing huge neg. value */
2404  SCIP_Real delta, /**< value to subtract from stored minactivity
2405  * (contribution of the variable set to zero when getting residual activity) */
2406  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2407  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2408  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2409  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2410  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2411  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2412  )
2413 {
2414  assert(scip != NULL);
2415  assert(consdata != NULL);
2416  assert(posinf >= 0);
2417  assert(neginf >= 0);
2418  assert(poshuge >= 0);
2419  assert(neghuge >= 0);
2420  assert(minactivity != NULL);
2421  assert(isrelax != NULL);
2422  assert(issettoinfinity != NULL);
2423 
2424  /* if we have pos. infinite contributions, the minactivity is +infty */
2425  if( posinf > 0 )
2426  {
2427  *minactivity = SCIPinfinity(scip);
2428  *issettoinfinity = TRUE;
2429  *isrelax = FALSE;
2430  }
2431  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2432  else if( neginf > 0 )
2433  {
2434  *minactivity = -SCIPinfinity(scip);
2435  *issettoinfinity = TRUE;
2436  *isrelax = FALSE;
2437  }
2438  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2439  else if( neghuge > 0 )
2440  {
2441  *minactivity = -SCIPinfinity(scip);
2442  *issettoinfinity = TRUE;
2443  *isrelax = TRUE;
2444  }
2445  /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2446  else if( !goodrelax && poshuge > 0 )
2447  {
2448  *minactivity = -SCIPinfinity(scip);
2449  *issettoinfinity = TRUE;
2450  *isrelax = TRUE;
2451  }
2452  else
2453  {
2454  SCIP_Real tmpactivity;
2455 
2456  /* recompute minactivity if it is not valid */
2457  if( global )
2458  {
2459  if( !consdata->validglbminact )
2460  consdataRecomputeGlbMinactivity(scip, consdata);
2461  assert(consdata->validglbminact);
2462 
2463  tmpactivity = QUAD_TO_DBL(consdata->glbminactivity);
2464  }
2465  else
2466  {
2467  if( !consdata->validminact )
2468  consdataRecomputeMinactivity(scip, consdata);
2469  assert(consdata->validminact);
2470 
2471  tmpactivity = QUAD_TO_DBL(consdata->minactivity);
2472  }
2473 
2474  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2475  * a feasible relaxation of the minactivity is the number of positive huge contributions
2476  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2477  */
2478  if( poshuge > 0 )
2479  {
2480  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2481  *issettoinfinity = FALSE;
2482  *isrelax = TRUE;
2483  }
2484  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2485  else
2486  {
2487  *minactivity = tmpactivity - delta;
2488  *issettoinfinity = FALSE;
2489  *isrelax = FALSE;
2490  }
2491  }
2492 }
2493 
2494 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2495  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2496  */
2497 static
2498 void getMaxActivity(
2499  SCIP* scip, /**< SCIP data structure */
2500  SCIP_CONSDATA* consdata, /**< linear constraint */
2501  int posinf, /**< number of coefficients contributing pos. infinite value */
2502  int neginf, /**< number of coefficients contributing neg. infinite value */
2503  int poshuge, /**< number of coefficients contributing huge pos. value */
2504  int neghuge, /**< number of coefficients contributing huge neg. value */
2505  SCIP_Real delta, /**< value to subtract from stored maxactivity
2506  * (contribution of the variable set to zero when getting residual activity) */
2507  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2508  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2509  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2510  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2511  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2512  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2513  )
2514 {
2515  assert(scip != NULL);
2516  assert(consdata != NULL);
2517  assert(posinf >= 0);
2518  assert(neginf >= 0);
2519  assert(poshuge >= 0);
2520  assert(neghuge >= 0);
2521  assert(maxactivity != NULL);
2522  assert(isrelax != NULL);
2523  assert(issettoinfinity != NULL);
2524 
2525  /* if we have neg. infinite contributions, the maxactivity is -infty */
2526  if( neginf > 0 )
2527  {
2528  *maxactivity = -SCIPinfinity(scip);
2529  *issettoinfinity = TRUE;
2530  *isrelax = FALSE;
2531  }
2532  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2533  else if( posinf > 0 )
2534  {
2535  *maxactivity = SCIPinfinity(scip);
2536  *issettoinfinity = TRUE;
2537  *isrelax = FALSE;
2538  }
2539  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2540  else if( poshuge > 0 )
2541  {
2542  *maxactivity = SCIPinfinity(scip);
2543  *issettoinfinity = TRUE;
2544  *isrelax = TRUE;
2545  }
2546  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2547  else if( !goodrelax && neghuge > 0 )
2548  {
2549  *maxactivity = SCIPinfinity(scip);
2550  *issettoinfinity = TRUE;
2551  *isrelax = TRUE;
2552  }
2553  else
2554  {
2555  SCIP_Real tmpactivity;
2556 
2557  /* recompute maxactivity if it is not valid */
2558  if( global )
2559  {
2560  if( !consdata->validglbmaxact )
2561  consdataRecomputeGlbMaxactivity(scip, consdata);
2562  assert(consdata->validglbmaxact);
2563 
2564  tmpactivity = QUAD_TO_DBL(consdata->glbmaxactivity);
2565  }
2566  else
2567  {
2568  if( !consdata->validmaxact )
2569  consdataRecomputeMaxactivity(scip, consdata);
2570  assert(consdata->validmaxact);
2571 
2572  tmpactivity = QUAD_TO_DBL(consdata->maxactivity);
2573  }
2574 
2575  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2576  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2577  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2578  */
2579  if( neghuge > 0 )
2580  {
2581  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2582  *issettoinfinity = FALSE;
2583  *isrelax = TRUE;
2584  }
2585  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2586  else
2587  {
2588  *maxactivity = tmpactivity - delta;
2589  *issettoinfinity = FALSE;
2590  *isrelax = FALSE;
2591  }
2592  }
2593 }
2594 
2595 /** gets activity bounds for constraint */
2596 static
2598  SCIP* scip, /**< SCIP data structure */
2599  SCIP_CONSDATA* consdata, /**< linear constraint */
2600  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2601  * relaxed activities ignored, anyway? */
2602  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2603  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2604  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2605  * i.e. <= the exact minactivity (in case of huge contributions),
2606  * or equal to the exact minimal activity */
2607  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2608  * i.e. >= the exact maxactivity (in case of huge contributions),
2609  * or equal to the exact maximal activity */
2610  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2611  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2612 
2613  )
2614 {
2615  assert(scip != NULL);
2616  assert(consdata != NULL);
2617  assert(minactivity != NULL);
2618  assert(maxactivity != NULL);
2619  assert(isminsettoinfinity != NULL);
2620  assert(ismaxsettoinfinity != NULL);
2621 
2622  if( !consdata->validactivities )
2623  {
2624  consdataCalcActivities(scip, consdata);
2625  assert(consdata->validminact);
2626  assert(consdata->validmaxact);
2627  }
2628  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2629  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2630  assert(consdata->minactivityneginf >= 0);
2631  assert(consdata->minactivityposinf >= 0);
2632  assert(consdata->maxactivityneginf >= 0);
2633  assert(consdata->maxactivityposinf >= 0);
2634 
2635  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2636  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2637  minactivity, minisrelax, isminsettoinfinity);
2638 
2639  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2640  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2641  maxactivity, maxisrelax, ismaxsettoinfinity);
2642 }
2643 
2644 /** calculates activity bounds for constraint after setting variable to zero */
2645 static
2647  SCIP* scip, /**< SCIP data structure */
2648  SCIP_CONSDATA* consdata, /**< linear constraint */
2649  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2650  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2651  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2652  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2653  )
2654 {
2655  SCIP_VAR* var;
2656  SCIP_Real val;
2657  SCIP_Real lb;
2658  SCIP_Real ub;
2659  int v;
2660 
2661  assert(scip != NULL);
2662  assert(consdata != NULL);
2663  assert(cancelvar != NULL);
2664  assert(resactivity != NULL);
2666  *resactivity = 0.0;
2667 
2668  for( v = 0; v < consdata->nvars; ++v )
2669  {
2670  var = consdata->vars[v];
2671  assert(var != NULL);
2672  if( var == cancelvar )
2673  continue;
2674 
2675  val = consdata->vals[v];
2676 
2677  if( useglobalbounds )
2678  {
2679  lb = SCIPvarGetLbGlobal(var);
2680  ub = SCIPvarGetUbGlobal(var);
2681  }
2682  else
2683  {
2684  lb = SCIPvarGetLbLocal(var);
2685  ub = SCIPvarGetUbLocal(var);
2686  }
2687 
2688  assert(!SCIPisZero(scip, val));
2689  assert(SCIPisLE(scip, lb, ub));
2690 
2691  if( val > 0.0 )
2692  {
2693  if( isminresact )
2694  {
2695  assert(!SCIPisInfinity(scip, -lb));
2696  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2697  *resactivity += val*lb;
2698  }
2699  else
2700  {
2701  assert(!SCIPisInfinity(scip, ub));
2702  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2703  *resactivity += val*ub;
2704  }
2705  }
2706  else
2707  {
2708  if( isminresact)
2709  {
2710  assert(!SCIPisInfinity(scip, ub));
2711  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2712  *resactivity += val*ub;
2713  }
2714  else
2715  {
2716  assert(!SCIPisInfinity(scip, -lb));
2717  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2718  *resactivity += val*lb;
2719  }
2720  }
2721  }
2722  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2723 }
2724 
2725 /** gets activity bounds for constraint after setting variable to zero */
2726 static
2728  SCIP* scip, /**< SCIP data structure */
2729  SCIP_CONSDATA* consdata, /**< linear constraint */
2730  SCIP_VAR* var, /**< variable to calculate activity residual for */
2731  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2732  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2733  * relaxed acticities ignored, anyway? */
2734  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2735  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2736  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2737  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2738  * contributions), or equal to the exact residual minactivity */
2739  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2740  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2741  * contributions), or equal to the exact residual minactivity */
2742  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2743  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2744  )
2745 {
2746  SCIP_Real minactbound;
2747  SCIP_Real maxactbound;
2748  SCIP_Real absval;
2749 
2750  assert(scip != NULL);
2751  assert(consdata != NULL);
2752  assert(var != NULL);
2753  assert(minresactivity != NULL);
2754  assert(maxresactivity != NULL);
2755  assert(minisrelax != NULL);
2756  assert(maxisrelax != NULL);
2757  assert(isminsettoinfinity != NULL);
2758  assert(ismaxsettoinfinity != NULL);
2759 
2760  /* get activity bounds of linear constraint */
2761  if( !consdata->validactivities )
2762  {
2763  consdataCalcActivities(scip, consdata);
2764  assert(consdata->validminact);
2765  assert(consdata->validmaxact);
2766  }
2767  assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID);
2768  assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID);
2769  assert(consdata->minactivityneginf >= 0);
2770  assert(consdata->minactivityposinf >= 0);
2771  assert(consdata->maxactivityneginf >= 0);
2772  assert(consdata->maxactivityposinf >= 0);
2773  assert(consdata->minactivityneghuge >= 0);
2774  assert(consdata->minactivityposhuge >= 0);
2775  assert(consdata->maxactivityneghuge >= 0);
2776  assert(consdata->maxactivityposhuge >= 0);
2777 
2778  if( val > 0.0 )
2779  {
2780  minactbound = SCIPvarGetLbLocal(var);
2781  maxactbound = SCIPvarGetUbLocal(var);
2782  absval = val;
2783  }
2784  else
2785  {
2786  minactbound = -SCIPvarGetUbLocal(var);
2787  maxactbound = -SCIPvarGetLbLocal(var);
2788  absval = -val;
2789  }
2790 
2791  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2792  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2793  */
2794  if( SCIPisInfinity(scip, minactbound) )
2795  {
2796  assert(consdata->minactivityposinf >= 1);
2797 
2798  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2799  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2800  minresactivity, minisrelax, isminsettoinfinity);
2801  }
2802  else if( SCIPisInfinity(scip, -minactbound) )
2803  {
2804  assert(consdata->minactivityneginf >= 1);
2805 
2806  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2807  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2808  minresactivity, minisrelax, isminsettoinfinity);
2809  }
2810  else if( SCIPisHugeValue(scip, minactbound * absval) )
2811  {
2812  assert(consdata->minactivityposhuge >= 1);
2813 
2814  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2815  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2816  minresactivity, minisrelax, isminsettoinfinity);
2817  }
2818  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2819  {
2820  assert(consdata->minactivityneghuge >= 1);
2821 
2822  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2823  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2824  minresactivity, minisrelax, isminsettoinfinity);
2825  }
2826  else
2827  {
2828  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2829  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2830  minresactivity, minisrelax, isminsettoinfinity);
2831  }
2832 
2833  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2834  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2835  */
2836  if( SCIPisInfinity(scip, -maxactbound) )
2837  {
2838  assert(consdata->maxactivityneginf >= 1);
2839 
2840  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2841  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2842  maxresactivity, maxisrelax, ismaxsettoinfinity);
2843  }
2844  else if( SCIPisInfinity(scip, maxactbound) )
2845  {
2846  assert(consdata->maxactivityposinf >= 1);
2847 
2848  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2849  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2850  maxresactivity, maxisrelax, ismaxsettoinfinity);
2851  }
2852  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2853  {
2854  assert(consdata->maxactivityposhuge >= 1);
2855 
2856  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2857  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2858  maxresactivity, maxisrelax, ismaxsettoinfinity);
2859  }
2860  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2861  {
2862  assert(consdata->maxactivityneghuge >= 1);
2863 
2864  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2865  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2866  maxresactivity, maxisrelax, ismaxsettoinfinity);
2867  }
2868  else
2869  {
2870  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2871  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2872  maxresactivity, maxisrelax, ismaxsettoinfinity);
2873  }
2874 }
2875 
2876 /** gets global activity bounds for constraint */
2877 static
2879  SCIP* scip, /**< SCIP data structure */
2880  SCIP_CONSDATA* consdata, /**< linear constraint */
2881  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2882  * relaxed acticities ignored, anyway? */
2883  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2884  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2885  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2886  * i.e. <= the exact minactivity (in case of huge contributions),
2887  * or equal to the exact minimal activity */
2888  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2889  * i.e. >= the exact maxactivity (in case of huge contributions),
2890  * or equal to the exact maximal activity */
2891  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2892  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2893  )
2894 {
2895  assert(scip != NULL);
2896  assert(consdata != NULL);
2897  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2898  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2899 
2900  if( !consdata->validactivities )
2901  {
2902  consdataCalcActivities(scip, consdata);
2903  assert(consdata->validglbminact);
2904  assert(consdata->validglbmaxact);
2905  }
2906  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2907  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2908  assert(consdata->glbminactivityneginf >= 0);
2909  assert(consdata->glbminactivityposinf >= 0);
2910  assert(consdata->glbmaxactivityneginf >= 0);
2911  assert(consdata->glbmaxactivityposinf >= 0);
2912  assert(consdata->glbminactivityneghuge >= 0);
2913  assert(consdata->glbminactivityposhuge >= 0);
2914  assert(consdata->glbmaxactivityneghuge >= 0);
2915  assert(consdata->glbmaxactivityposhuge >= 0);
2916 
2917  if( glbminactivity != NULL )
2918  {
2919  assert(isminsettoinfinity != NULL);
2920  assert(minisrelax != NULL);
2921 
2922  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2923  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2924  glbminactivity, minisrelax, isminsettoinfinity);
2925  }
2926 
2927  if( glbmaxactivity != NULL )
2928  {
2929  assert(ismaxsettoinfinity != NULL);
2930  assert(maxisrelax != NULL);
2931 
2932  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2933  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2934  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2935  }
2936 }
2937 
2938 /** gets global activity bounds for constraint after setting variable to zero */
2939 static
2941  SCIP* scip, /**< SCIP data structure */
2942  SCIP_CONSDATA* consdata, /**< linear constraint */
2943  SCIP_VAR* var, /**< variable to calculate activity residual for */
2944  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2945  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2946  * relaxed acticities ignored, anyway? */
2947  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2948  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2949  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2950  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2951  * contributions), or equal to the exact residual minactivity */
2952  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2953  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2954  * contributions), or equal to the exact residual minactivity */
2955  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2956  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2957  )
2958 {
2959  SCIP_Real minactbound;
2960  SCIP_Real maxactbound;
2961  SCIP_Real absval;
2962 
2963  assert(scip != NULL);
2964  assert(consdata != NULL);
2965  assert(var != NULL);
2966  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2967  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2968 
2969  /* get activity bounds of linear constraint */
2970  if( !consdata->validactivities )
2971  consdataCalcActivities(scip, consdata);
2972 
2973  assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID);
2974  assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID);
2975  assert(consdata->glbminactivityneginf >= 0);
2976  assert(consdata->glbminactivityposinf >= 0);
2977  assert(consdata->glbmaxactivityneginf >= 0);
2978  assert(consdata->glbmaxactivityposinf >= 0);
2979 
2980  if( val > 0.0 )
2981  {
2982  minactbound = SCIPvarGetLbGlobal(var);
2983  maxactbound = SCIPvarGetUbGlobal(var);
2984  absval = val;
2985  }
2986  else
2987  {
2988  minactbound = -SCIPvarGetUbGlobal(var);
2989  maxactbound = -SCIPvarGetLbGlobal(var);
2990  absval = -val;
2991  }
2992 
2993  if( minresactivity != NULL )
2994  {
2995  assert(isminsettoinfinity != NULL);
2996  assert(minisrelax != NULL);
2997 
2998  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2999  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3000  */
3001  if( SCIPisInfinity(scip, minactbound) )
3002  {
3003  assert(consdata->glbminactivityposinf >= 1);
3004 
3005  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
3006  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3007  minresactivity, minisrelax, isminsettoinfinity);
3008  }
3009  else if( SCIPisInfinity(scip, -minactbound) )
3010  {
3011  assert(consdata->glbminactivityneginf >= 1);
3012 
3013  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
3014  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3015  minresactivity, minisrelax, isminsettoinfinity);
3016  }
3017  else if( SCIPisHugeValue(scip, minactbound * absval) )
3018  {
3019  assert(consdata->glbminactivityposhuge >= 1);
3020 
3021  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3022  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
3023  minresactivity, minisrelax, isminsettoinfinity);
3024  }
3025  else if( SCIPisHugeValue(scip, -minactbound * absval) )
3026  {
3027  assert(consdata->glbminactivityneghuge >= 1);
3028 
3029  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3030  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3031  minresactivity, minisrelax, isminsettoinfinity);
3032  }
3033  else
3034  {
3035  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3036  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3037  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3038  }
3039  }
3040 
3041  if( maxresactivity != NULL )
3042  {
3043  assert(ismaxsettoinfinity != NULL);
3044  assert(maxisrelax != NULL);
3045 
3046  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3047  * and contribution of variable set to zero that has to be subtracted from finite part of activity
3048  */
3049  if( SCIPisInfinity(scip, -maxactbound) )
3050  {
3051  assert(consdata->glbmaxactivityneginf >= 1);
3052 
3053  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3054  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3055  maxresactivity, maxisrelax, ismaxsettoinfinity);
3056  }
3057  else if( SCIPisInfinity(scip, maxactbound) )
3058  {
3059  assert(consdata->glbmaxactivityposinf >= 1);
3060 
3061  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3062  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3063  maxresactivity, maxisrelax, ismaxsettoinfinity);
3064  }
3065  else if( SCIPisHugeValue(scip, absval * maxactbound) )
3066  {
3067  assert(consdata->glbmaxactivityposhuge >= 1);
3068 
3069  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3070  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3071  maxresactivity, maxisrelax, ismaxsettoinfinity);
3072  }
3073  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3074  {
3075  assert(consdata->glbmaxactivityneghuge >= 1);
3076 
3077  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3078  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3079  maxresactivity, maxisrelax, ismaxsettoinfinity);
3080  }
3081  else
3082  {
3083  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3084  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3085  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3086  }
3087  }
3088 }
3089 
3090 /** calculates the activity of the linear constraint for given solution */
3091 static
3093  SCIP* scip, /**< SCIP data structure */
3094  SCIP_CONSDATA* consdata, /**< linear constraint data */
3095  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
3096  )
3097 {
3098  SCIP_Real activity;
3099 
3100  assert(scip != NULL);
3101  assert(consdata != NULL);
3102 
3103  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3104  activity = consdataComputePseudoActivity(scip, consdata);
3105  else
3106  {
3107  SCIP_Real solval;
3108  int nposinf;
3109  int nneginf;
3110  SCIP_Bool negsign;
3111  int v;
3112 
3113  activity = 0.0;
3114  nposinf = 0;
3115  nneginf = 0;
3116 
3117  for( v = 0; v < consdata->nvars; ++v )
3118  {
3119  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3120 
3121  if( consdata->vals[v] < 0 )
3122  negsign = TRUE;
3123  else
3124  negsign = FALSE;
3125 
3126  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3127  ++nposinf;
3128  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3129  ++nneginf;
3130  else
3131  activity += consdata->vals[v] * solval;
3132  }
3133  assert(nneginf >= 0 && nposinf >= 0);
3134 
3135  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3136 
3137  /* check for amount of infinity values and correct the activity */
3138  if( nposinf > 0 && nneginf > 0 )
3139  activity = (consdata->rhs + consdata->lhs) / 2;
3140  else if( nposinf > 0 )
3141  activity = SCIPinfinity(scip);
3142  else if( nneginf > 0 )
3143  activity = -SCIPinfinity(scip);
3144 
3145  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3146  }
3147 
3148  if( activity == SCIP_INVALID ) /*lint !e777*/
3149  return activity;
3150  else if( activity < 0 )
3151  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3152  else
3153  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3154 
3155  return activity;
3156 }
3157 
3158 /** calculates the feasibility of the linear constraint for given solution */
3159 static
3161  SCIP* scip, /**< SCIP data structure */
3162  SCIP_CONSDATA* consdata, /**< linear constraint data */
3163  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3164  )
3165 {
3166  SCIP_Real activity;
3167 
3168  assert(scip != NULL);
3169  assert(consdata != NULL);
3170 
3171  activity = consdataGetActivity(scip, consdata, sol);
3172 
3173  if( activity == SCIP_INVALID ) /*lint !e777*/
3174  return -SCIPinfinity(scip);
3175 
3176  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3177 }
3178 
3179 /** updates bit signatures after adding a single coefficient */
3180 static
3182  SCIP_CONSDATA* consdata, /**< linear constraint data */
3183  int pos /**< position of coefficient to update signatures for */
3184  )
3185 {
3186  uint64_t varsignature;
3187  SCIP_Real lb;
3188  SCIP_Real ub;
3189  SCIP_Real val;
3190 
3191  assert(consdata != NULL);
3192  assert(consdata->validsignature);
3193 
3194  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3195  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3196  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3197  val = consdata->vals[pos];
3198  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3199  consdata->possignature |= varsignature;
3200  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3201  consdata->negsignature |= varsignature;
3202 }
3203 
3204 /** calculates the bit signatures of the given constraint data */
3205 static
3207  SCIP_CONSDATA* consdata /**< linear constraint data */
3208  )
3209 {
3210  assert(consdata != NULL);
3211 
3212  if( !consdata->validsignature )
3213  {
3214  int i;
3215 
3216  consdata->validsignature = TRUE;
3217  consdata->possignature = 0;
3218  consdata->negsignature = 0;
3219  for( i = 0; i < consdata->nvars; ++i )
3220  consdataUpdateSignatures(consdata, i);
3221  }
3222 }
3223 
3224 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3225 static
3226 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3227 { /*lint --e{715}*/
3228  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3229  SCIP_VAR* var1;
3230  SCIP_VAR* var2;
3231 
3232  assert(consdata != NULL);
3233  assert(0 <= ind1 && ind1 < consdata->nvars);
3234  assert(0 <= ind2 && ind2 < consdata->nvars);
3235 
3236  var1 = consdata->vars[ind1];
3237  var2 = consdata->vars[ind2];
3238 
3239  /* exactly one variable is binary */
3240  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3241  {
3242  return (SCIPvarIsBinary(var1) ? -1 : +1);
3243  }
3244  /* both variables are binary */
3245  else if( SCIPvarIsBinary(var1) )
3246  {
3247  return SCIPvarCompare(var1, var2);
3248  }
3249  else
3250  {
3251  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3252  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3253 
3254  if( vartype1 < vartype2 )
3255  return -1;
3256  else if( vartype1 > vartype2 )
3257  return +1;
3258  else
3259  return SCIPvarCompare(var1, var2);
3260  }
3261 }
3262 
3263 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3264 static
3265 SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3266 { /*lint --e{715}*/
3267  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3268  SCIP_VAR* var1;
3269  SCIP_VAR* var2;
3270 
3271  assert(consdata != NULL);
3272  assert(0 <= ind1 && ind1 < consdata->nvars);
3273  assert(0 <= ind2 && ind2 < consdata->nvars);
3274 
3275  var1 = consdata->vars[ind1];
3276  var2 = consdata->vars[ind2];
3277 
3278  /* exactly one variable is binary */
3279  if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3280  {
3281  return (SCIPvarIsBinary(var1) ? -1 : +1);
3282  }
3283  /* both variables are binary */
3284  else if( SCIPvarIsBinary(var1) )
3285  {
3286  SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3287  SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3288 
3289  if( EPSGT(abscoef1, abscoef2, 1e-9) )
3290  return -1;
3291  else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3292  return +1;
3293  else
3294  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3295  }
3296  else
3297  {
3298  SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3299  SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3300 
3301  if( vartype1 < vartype2 )
3302  {
3303  return -1;
3304  }
3305  else if( vartype1 > vartype2 )
3306  {
3307  return +1;
3308  }
3309  else
3310  {
3311  /* both variables are continuous */
3312  if( !SCIPvarIsIntegral(var1) )
3313  {
3314  assert(!SCIPvarIsIntegral(var2));
3315  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3316  }
3317  else
3318  {
3319  SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3320  SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3321 
3322  if( EPSGT(abscont1, abscont2, 1e-9) )
3323  return -1;
3324  else if( EPSGT(abscont2, abscont1, 1e-9) )
3325  return +1;
3326  else
3327  return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3328  }
3329  }
3330  }
3331 }
3332 
3333 /** permutes the constraint's variables according to a given permutation. */
3334 static
3335 void permSortConsdata(
3336  SCIP_CONSDATA* consdata, /**< the constraint data */
3337  int* perm, /**< the target permutation */
3338  int nvars /**< the number of variables */
3339  )
3340 { /*lint --e{715}*/
3341  SCIP_VAR* varv;
3342  SCIP_EVENTDATA* eventdatav;
3343  SCIP_Real valv;
3344  int v;
3345  int i;
3346  int nexti;
3347 
3348  assert(perm != NULL);
3349  assert(consdata != NULL);
3350 
3351  /* permute the variables in the linear constraint according to the target permutation */
3352  eventdatav = NULL;
3353  for( v = 0; v < nvars; ++v )
3354  {
3355  if( perm[v] != v )
3356  {
3357  varv = consdata->vars[v];
3358  valv = consdata->vals[v];
3359  if( consdata->eventdata != NULL )
3360  eventdatav = consdata->eventdata[v];
3361  i = v;
3362  do
3363  {
3364  assert(0 <= perm[i] && perm[i] < nvars);
3365  assert(perm[i] != i);
3366  consdata->vars[i] = consdata->vars[perm[i]];
3367  consdata->vals[i] = consdata->vals[perm[i]];
3368  if( consdata->eventdata != NULL )
3369  {
3370  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3371  consdata->eventdata[i]->varpos = i;
3372  }
3373  nexti = perm[i];
3374  perm[i] = i;
3375  i = nexti;
3376  }
3377  while( perm[i] != v );
3378  consdata->vars[i] = varv;
3379  consdata->vals[i] = valv;
3380  if( consdata->eventdata != NULL )
3381  {
3382  consdata->eventdata[i] = eventdatav;
3383  consdata->eventdata[i]->varpos = i;
3384  }
3385  perm[i] = i;
3386  }
3387  }
3388 #ifdef SCIP_DEBUG
3389  /* check sorting */
3390  for( v = 0; v < nvars; ++v )
3391  {
3392  assert(perm[v] == v);
3393  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3394  }
3395 #endif
3396 }
3397 
3398 /** sorts linear constraint's variables depending on the stage of the solving process:
3399  * - during PRESOLVING
3400  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3401  * and the variables of the same type by non-decreasing variable index
3402  *
3403  * - during SOLVING
3404  * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3405  * and binary and integer variables by their global max activity delta (within each group),
3406  * ties within a group are broken by problem index of the variable.
3407  *
3408  * This fastens the propagation time of the constraint handler.
3409  */
3410 static
3412  SCIP* scip, /**< SCIP data structure */
3413  SCIP_CONSDATA* consdata /**< linear constraint data */
3414  )
3415 {
3416  assert(scip != NULL);
3417  assert(consdata != NULL);
3418 
3419  /* check if there are variables for sorting */
3420  if( consdata->nvars <= 1 )
3421  {
3422  consdata->indexsorted = TRUE;
3423  consdata->coefsorted = TRUE;
3424  consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3425  }
3426  else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3427  || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3428  {
3429  int* perm;
3430  int v;
3431 
3432  /* get temporary memory to store the sorted permutation */
3433  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3434 
3435  /* call sorting method */
3436  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3437  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3438  else
3439  SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3440 
3441  permSortConsdata(consdata, perm, consdata->nvars);
3442 
3443  /* free temporary memory */
3444  SCIPfreeBufferArray(scip, &perm);
3445 
3446  if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE )
3447  {
3448  consdata->indexsorted = FALSE;
3449  consdata->coefsorted = TRUE;
3450 
3451  /* count binary variables in the sorted vars array */
3452  consdata->nbinvars = 0;
3453  for( v = 0; v < consdata->nvars; ++v )
3454  {
3455  if( SCIPvarIsBinary(consdata->vars[v]) )
3456  ++consdata->nbinvars;
3457  else
3458  break;
3459  }
3460  }
3461  else
3462  {
3463  consdata->indexsorted = TRUE;
3464  consdata->coefsorted = FALSE;
3465  }
3466  }
3467 
3468  return SCIP_OKAY;
3469 }
3470 
3471 
3472 /*
3473  * local linear constraint handler methods
3474  */
3475 
3476 /** sets left hand side of linear constraint */
3477 static
3479  SCIP* scip, /**< SCIP data structure */
3480  SCIP_CONS* cons, /**< linear constraint */
3481  SCIP_Real lhs /**< new left hand side */
3482  )
3483 {
3484  SCIP_CONSDATA* consdata;
3485  SCIP_Bool locked;
3486  int i;
3487 
3488  assert(scip != NULL);
3489  assert(cons != NULL);
3490  assert(!SCIPisInfinity(scip, lhs));
3491 
3492  /* adjust value to not be smaller than -inf */
3493  if ( SCIPisInfinity(scip, -lhs) )
3494  lhs = -SCIPinfinity(scip);
3495 
3496  consdata = SCIPconsGetData(cons);
3497  assert(consdata != NULL);
3498  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3499  assert(!SCIPisInfinity(scip, consdata->lhs));
3500 
3501  /* check whether the side is not changed */
3502  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3503  return SCIP_OKAY;
3504 
3505  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3506  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3507  {
3508  consdata->rhs = lhs;
3509  assert(consdata->row == NULL);
3510  }
3511 
3512  locked = FALSE;
3513  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3514  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3515 
3516  /* if necessary, update the rounding locks of variables */
3517  if( locked )
3518  {
3519  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3520  {
3521  SCIP_VAR** vars;
3522  SCIP_Real* vals;
3523  int v;
3524 
3525  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3526  vars = consdata->vars;
3527  vals = consdata->vals;
3528 
3529  for( v = 0; v < consdata->nvars; ++v )
3530  {
3531  assert(vars[v] != NULL);
3532  assert(!SCIPisZero(scip, vals[v]));
3533 
3534  if( SCIPisPositive(scip, vals[v]) )
3535  {
3536  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3537  }
3538  else
3539  {
3540  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3541  }
3542  }
3543  }
3544  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3545  {
3546  SCIP_VAR** vars;
3547  SCIP_Real* vals;
3548  int v;
3549 
3550  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3551  vars = consdata->vars;
3552  vals = consdata->vals;
3553 
3554  for( v = 0; v < consdata->nvars; ++v )
3555  {
3556  assert(vars[v] != NULL);
3557  assert(!SCIPisZero(scip, vals[v]));
3558 
3559  if( SCIPisPositive(scip, vals[v]) )
3560  {
3561  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3562  }
3563  else
3564  {
3565  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3566  }
3567  }
3568  }
3569  }
3570 
3571  /* 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 */
3572  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3573  {
3574  consdata->boundstightened = 0;
3575  consdata->presolved = FALSE;
3576  consdata->cliquesadded = FALSE;
3577  consdata->implsadded = FALSE;
3578 
3579  /* mark the constraint for propagation */
3580  if( SCIPconsIsTransformed(cons) )
3581  {
3582  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3583  }
3584  }
3585 
3586  /* set new left hand side and update constraint data */
3587  consdata->lhs = lhs;
3588  consdata->changed = TRUE;
3589  consdata->normalized = FALSE;
3590  consdata->upgradetried = FALSE;
3591  consdata->rangedrowpropagated = 0;
3592 
3593  /* update the lhs of the LP row */
3594  if( consdata->row != NULL )
3595  {
3596  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3597  }
3598 
3599  return SCIP_OKAY;
3600 }
3601 
3602 /** sets right hand side of linear constraint */
3603 static
3605  SCIP* scip, /**< SCIP data structure */
3606  SCIP_CONS* cons, /**< linear constraint */
3607  SCIP_Real rhs /**< new right hand side */
3608  )
3609 {
3610  SCIP_CONSDATA* consdata;
3611  SCIP_Bool locked;
3612  int i;
3613 
3614  assert(scip != NULL);
3615  assert(cons != NULL);
3616  assert(!SCIPisInfinity(scip, -rhs));
3617 
3618  /* adjust value to not be larger than inf */
3619  if ( SCIPisInfinity(scip, rhs) )
3620  rhs = SCIPinfinity(scip);
3621 
3622  consdata = SCIPconsGetData(cons);
3623  assert(consdata != NULL);
3624  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3625  assert(!SCIPisInfinity(scip, -consdata->rhs));
3626 
3627  /* check whether the side is not changed */
3628  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3629  return SCIP_OKAY;
3630 
3631  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3632  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3633  {
3634  consdata->lhs = rhs;
3635  assert(consdata->row == NULL);
3636  }
3637 
3638  locked = FALSE;
3639  for( i = 0; i < NLOCKTYPES && !locked; i++ )
3640  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3641 
3642  /* if necessary, update the rounding locks of variables */
3643  if( locked )
3644  {
3645  assert(SCIPconsIsTransformed(cons));
3646 
3647  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3648  {
3649  SCIP_VAR** vars;
3650  SCIP_Real* vals;
3651  int v;
3652 
3653  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3654  vars = consdata->vars;
3655  vals = consdata->vals;
3656 
3657  for( v = 0; v < consdata->nvars; ++v )
3658  {
3659  assert(vars[v] != NULL);
3660  assert(!SCIPisZero(scip, vals[v]));
3661 
3662  if( SCIPisPositive(scip, vals[v]) )
3663  {
3664  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3665  }
3666  else
3667  {
3668  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3669  }
3670  }
3671  }
3672  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3673  {
3674  SCIP_VAR** vars;
3675  SCIP_Real* vals;
3676  int v;
3677 
3678  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3679  vars = consdata->vars;
3680  vals = consdata->vals;
3681 
3682  for( v = 0; v < consdata->nvars; ++v )
3683  {
3684  assert(vars[v] != NULL);
3685  assert(!SCIPisZero(scip, vals[v]));
3686 
3687  if( SCIPisPositive(scip, vals[v]) )
3688  {
3689  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3690  }
3691  else
3692  {
3693  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3694  }
3695  }
3696  }
3697  }
3698 
3699  /* 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 */
3700  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3701  {
3702  consdata->boundstightened = 0;
3703  consdata->presolved = FALSE;
3704  consdata->cliquesadded = FALSE;
3705  consdata->implsadded = FALSE;
3706 
3707  /* mark the constraint for propagation */
3708  if( SCIPconsIsTransformed(cons) )
3709  {
3710  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3711  }
3712  }
3713 
3714  /* set new right hand side and update constraint data */
3715  consdata->rhs = rhs;
3716  consdata->changed = TRUE;
3717  consdata->normalized = FALSE;
3718  consdata->upgradetried = FALSE;
3719  consdata->rangedrowpropagated = 0;
3720 
3721  /* update the rhs of the LP row */
3722  if( consdata->row != NULL )
3723  {
3724  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3725  }
3726 
3727  return SCIP_OKAY;
3728 }
3729 
3730 /** adds coefficient in linear constraint */
3731 static
3733  SCIP* scip, /**< SCIP data structure */
3734  SCIP_CONS* cons, /**< linear constraint */
3735  SCIP_VAR* var, /**< variable of constraint entry */
3736  SCIP_Real val /**< coefficient of constraint entry */
3737  )
3738 {
3739  SCIP_CONSDATA* consdata;
3740  SCIP_Bool transformed;
3741 
3742  assert(scip != NULL);
3743  assert(cons != NULL);
3744  assert(var != NULL);
3745 
3746  /* relaxation-only variables must not be used in checked or enforced constraints */
3747  assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3748 
3749  /* ignore coefficient if it is nearly zero */
3750  if( SCIPisZero(scip, val) )
3751  return SCIP_OKAY;
3752 
3753  consdata = SCIPconsGetData(cons);
3754  assert(consdata != NULL);
3755 
3756  /* are we in the transformed problem? */
3757  transformed = SCIPconsIsTransformed(cons);
3758 
3759  /* always use transformed variables in transformed constraints */
3760  if( transformed )
3761  {
3762  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3763  }
3764  assert(var != NULL);
3765  assert(transformed == SCIPvarIsTransformed(var));
3766 
3767  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3768  consdata->vars[consdata->nvars] = var;
3769  consdata->vals[consdata->nvars] = val;
3770  consdata->nvars++;
3771 
3772  /* capture variable */
3773  SCIP_CALL( SCIPcaptureVar(scip, var) );
3774 
3775  /* if we are in transformed problem, the variable needs an additional event data */
3776  if( transformed )
3777  {
3778  if( consdata->eventdata != NULL )
3779  {
3780  SCIP_CONSHDLR* conshdlr;
3781  SCIP_CONSHDLRDATA* conshdlrdata;
3782 
3783  /* check for event handler */
3784  conshdlr = SCIPconsGetHdlr(cons);
3785  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3786  assert(conshdlrdata != NULL);
3787  assert(conshdlrdata->eventhdlr != NULL);
3788 
3789  /* initialize eventdata array */
3790  consdata->eventdata[consdata->nvars-1] = NULL;
3791 
3792  /* catch bound change events of variable */
3793  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3794  }
3795 
3796  /* update minimum and maximum activities */
3797  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3798 
3799  /* update maximum activity delta */
3800  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3801  {
3802  SCIP_Real lb;
3803  SCIP_Real ub;
3804 
3805  lb = SCIPvarGetLbLocal(var);
3806  ub = SCIPvarGetUbLocal(var);
3807 
3808  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3809  {
3810  consdata->maxactdelta = SCIPinfinity(scip);
3811  consdata->maxactdeltavar = var;
3812  }
3813  else
3814  {
3815  SCIP_Real domain = ub - lb;
3816  SCIP_Real delta = REALABS(val) * domain;
3817 
3818  if( delta > consdata->maxactdelta )
3819  {
3820  consdata->maxactdelta = delta;
3821  consdata->maxactdeltavar = var;
3822  }
3823  }
3824  }
3825  }
3826 
3827  /* install rounding locks for new variable */
3828  SCIP_CALL( lockRounding(scip, cons, var, val) );
3829 
3830  /* mark the constraint for propagation */
3831  if( transformed )
3832  {
3833  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3834  }
3835 
3836  consdata->boundstightened = 0;
3837  consdata->presolved = FALSE;
3838  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3839 
3840  if( consdata->validsignature )
3841  consdataUpdateSignatures(consdata, consdata->nvars-1);
3842 
3843  consdata->changed = TRUE;
3844  consdata->normalized = FALSE;
3845  consdata->upgradetried = FALSE;
3846  consdata->cliquesadded = FALSE;
3847  consdata->implsadded = FALSE;
3848  consdata->rangedrowpropagated = 0;
3849 
3850  if( consdata->nvars == 1 )
3851  {
3852  consdata->indexsorted = TRUE;
3853  consdata->coefsorted = TRUE;
3854  consdata->merged = TRUE;
3855  }
3856  else
3857  {
3858  consdata->merged = FALSE;
3859 
3860  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3861  {
3862  consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3863  consdata->coefsorted = FALSE;
3864  }
3865  else
3866  {
3867  consdata->indexsorted = FALSE;
3868  consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3869  }
3870  }
3871 
3872  /* update hascontvar and hasnonbinvar flags */
3873  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3874  {
3875  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3876 
3877  if( vartype != SCIP_VARTYPE_BINARY )
3878  {
3879  consdata->hasnonbinvar = TRUE;
3880 
3881  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3882  consdata->hascontvar = TRUE;
3883  }
3884  }
3885 
3886  /* add the new coefficient to the LP row */
3887  if( consdata->row != NULL )
3888  {
3889  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3890  }
3891 
3892  return SCIP_OKAY;
3893 }
3894 
3895 /** deletes coefficient at given position from linear constraint data */
3896 static
3898  SCIP* scip, /**< SCIP data structure */
3899  SCIP_CONS* cons, /**< linear constraint */
3900  int pos /**< position of coefficient to delete */
3901  )
3902 {
3903  SCIP_CONSDATA* consdata;
3904  SCIP_VAR* var;
3905  SCIP_Real val;
3906 
3907  assert(scip != NULL);
3908  assert(cons != NULL);
3909 
3910  consdata = SCIPconsGetData(cons);
3911  assert(consdata != NULL);
3912  assert(0 <= pos && pos < consdata->nvars);
3913 
3914  var = consdata->vars[pos];
3915  val = consdata->vals[pos];
3916  assert(var != NULL);
3917 
3918  /* remove rounding locks for deleted variable */
3919  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3920 
3921  /* if we are in transformed problem, delete the event data of the variable */
3922  if( SCIPconsIsTransformed(cons) )
3923  {
3924  SCIP_CONSHDLR* conshdlr;
3925  SCIP_CONSHDLRDATA* conshdlrdata;
3926 
3927  /* check for event handler */
3928  conshdlr = SCIPconsGetHdlr(cons);
3929  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3930  assert(conshdlrdata != NULL);
3931  assert(conshdlrdata->eventhdlr != NULL);
3932 
3933  /* drop bound change events of variable */
3934  if( consdata->eventdata != NULL )
3935  {
3936  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3937  assert(consdata->eventdata[pos] == NULL);
3938  }
3939  }
3940 
3941  /* move the last variable to the free slot */
3942  if( pos != consdata->nvars - 1 )
3943  {
3944  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3945  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3946 
3947  if( consdata->eventdata != NULL )
3948  {
3949  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3950  assert(consdata->eventdata[pos] != NULL);
3951  consdata->eventdata[pos]->varpos = pos;
3952  }
3953 
3954  consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3955  consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3956  }
3957  consdata->nvars--;
3958 
3959  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3960  * of the remaining variable, or give exactly 0.0)
3961  */
3962  if( consdata->nvars <= 1 )
3963  consdataInvalidateActivities(consdata);
3964  else
3965  {
3966  if( SCIPconsIsTransformed(cons) )
3967  {
3968  /* if we are in transformed problem, update minimum and maximum activities */
3969  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3970 
3971  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3972  * delta needs to be recalculated on the next real propagation
3973  */
3974  if( consdata->maxactdeltavar == var )
3975  {
3976  consdata->maxactdelta = SCIP_INVALID;
3977  consdata->maxactdeltavar = NULL;
3978  }
3979  }
3980  }
3981 
3982  /* mark the constraint for propagation */
3983  if( SCIPconsIsTransformed(cons) )
3984  {
3985  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3986  }
3987 
3988  consdata->boundstightened = 0;
3989  consdata->presolved = FALSE;
3990  consdata->validsignature = FALSE;
3991  consdata->changed = TRUE;
3992  consdata->normalized = FALSE;
3993  consdata->upgradetried = FALSE;
3994  consdata->cliquesadded = FALSE;
3995  consdata->implsadded = FALSE;
3996  consdata->rangedrowpropagated = 0;
3997 
3998  /* check if hasnonbinvar flag might be incorrect now */
3999  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
4000  {
4001  consdata->hasnonbinvalid = FALSE;
4002  }
4003 
4004  /* delete coefficient from the LP row */
4005  if( consdata->row != NULL )
4006  {
4007  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
4008  }
4009 
4010  /* release variable */
4011  SCIP_CALL( SCIPreleaseVar(scip, &var) );
4012 
4013  return SCIP_OKAY;
4014 }
4015 
4016 /** changes coefficient value at given position of linear constraint data */
4017 static
4019  SCIP* scip, /**< SCIP data structure */
4020  SCIP_CONS* cons, /**< linear constraint */
4021  int pos, /**< position of coefficient to delete */
4022  SCIP_Real newval /**< new value of coefficient */
4023  )
4024 {
4025  SCIP_CONSDATA* consdata;
4026  SCIP_VAR* var;
4027  SCIP_Real val;
4028  SCIP_Bool locked;
4029  int i;
4030 
4031  assert(scip != NULL);
4032  assert(cons != NULL);
4033  assert(!SCIPisZero(scip, newval));
4034 
4035  consdata = SCIPconsGetData(cons);
4036  assert(consdata != NULL);
4037  assert(0 <= pos && pos < consdata->nvars);
4038  assert(!SCIPisZero(scip, newval));
4039 
4040  var = consdata->vars[pos];
4041  val = consdata->vals[pos];
4042  assert(var != NULL);
4043  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
4044 
4045  locked = FALSE;
4046  for( i = 0; i < NLOCKTYPES && !locked; i++ )
4047  locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4048 
4049  /* if necessary, update the rounding locks of the variable */
4050  if( locked && newval * val < 0.0 )
4051  {
4052  assert(SCIPconsIsTransformed(cons));
4053 
4054  /* remove rounding locks for variable with old coefficient */
4055  SCIP_CALL( unlockRounding(scip, cons, var, val) );
4056 
4057  /* install rounding locks for variable with new coefficient */
4058  SCIP_CALL( lockRounding(scip, cons, var, newval) );
4059  }
4060 
4061  /* change the value */
4062  consdata->vals[pos] = newval;
4063 
4064  if( consdata->coefsorted )
4065  {
4066  if( pos > 0 )
4067  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4068  if( consdata->coefsorted && pos < consdata->nvars - 1 )
4069  consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4070  }
4071 
4072  /* update minimum and maximum activities */
4073  if( SCIPconsIsTransformed(cons) )
4074  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4075 
4076  /* mark the constraint for propagation */
4077  if( SCIPconsIsTransformed(cons) )
4078  {
4079  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4080  }
4081 
4082  consdata->boundstightened = 0;
4083  consdata->presolved = FALSE;
4084  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4085  consdata->changed = TRUE;
4086  consdata->normalized = FALSE;
4087  consdata->upgradetried = FALSE;
4088  consdata->cliquesadded = FALSE;
4089  consdata->implsadded = FALSE;
4090  consdata->rangedrowpropagated = 0;
4091 
4092  return SCIP_OKAY;
4093 }
4094 
4095 /** scales a linear constraint with a constant scalar */
4096 static
4098  SCIP* scip, /**< SCIP data structure */
4099  SCIP_CONS* cons, /**< linear constraint to scale */
4100  SCIP_Real scalar /**< value to scale constraint with */
4101  )
4102 {
4103  SCIP_CONSDATA* consdata;
4104  SCIP_Real newval;
4105  SCIP_Real absscalar;
4106  int i;
4107 
4108  assert(scip != NULL);
4109  assert(cons != NULL);
4110 
4111  consdata = SCIPconsGetData(cons);
4112  assert(consdata != NULL);
4113  assert(consdata->row == NULL);
4114  assert(!SCIPisEQ(scip, scalar, 1.0));
4115 
4116  if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4117  || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4118  {
4119  SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4120  SCIPconsGetName(cons), scalar);
4121 
4122  return SCIP_OKAY;
4123  }
4124 
4125  /* scale the coefficients */
4126  for( i = consdata->nvars - 1; i >= 0; --i )
4127  {
4128  newval = scalar * consdata->vals[i];
4129 
4130  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4131  * flooring down our new value
4132  */
4133  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4134  newval = SCIPfeasFloor(scip, newval + 0.5);
4135 
4136  if( SCIPisZero(scip, newval) )
4137  {
4138  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4139  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4140  SCIP_CALL( delCoefPos(scip, cons, i) );
4141  }
4142  else
4143  consdata->vals[i] = newval;
4144  }
4145 
4146  /* scale the sides */
4147  if( scalar < 0.0 )
4148  {
4149  SCIP_Real lhs;
4150 
4151  lhs = consdata->lhs;
4152  consdata->lhs = -consdata->rhs;
4153  consdata->rhs = -lhs;
4154  }
4155  absscalar = REALABS(scalar);
4156  if( !SCIPisInfinity(scip, -consdata->lhs) )
4157  {
4158  newval = absscalar * consdata->lhs;
4159 
4160  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4161  * flooring down our new value
4162  */
4163  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4164  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4165  else
4166  consdata->lhs = newval;
4167  }
4168  if( !SCIPisInfinity(scip, consdata->rhs) )
4169  {
4170  newval = absscalar * consdata->rhs;
4171 
4172  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4173  * our new value
4174  */
4175  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4176  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4177  else
4178  consdata->rhs = newval;
4179  }
4180 
4181  consdataInvalidateActivities(consdata);
4182  consdata->cliquesadded = FALSE;
4183  consdata->implsadded = FALSE;
4184 
4185  return SCIP_OKAY;
4186 }
4187 
4188 /** perform deletion of variables in all constraints of the constraint handler */
4189 static
4191  SCIP* scip, /**< SCIP data structure */
4192  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4193  SCIP_CONS** conss, /**< array of constraints */
4194  int nconss /**< number of constraints */
4195  )
4196 {
4197  SCIP_CONSDATA* consdata;
4198  int i;
4199  int v;
4200 
4201  assert(scip != NULL);
4202  assert(conshdlr != NULL);
4203  assert(conss != NULL);
4204  assert(nconss >= 0);
4205  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4206 
4207  /* iterate over all constraints */
4208  for( i = 0; i < nconss; i++ )
4209  {
4210  consdata = SCIPconsGetData(conss[i]);
4211 
4212  /* constraint is marked, that some of its variables were deleted */
4213  if( consdata->varsdeleted )
4214  {
4215  /* iterate over all variables of the constraint and delete them from the constraint */
4216  for( v = consdata->nvars - 1; v >= 0; --v )
4217  {
4218  if( SCIPvarIsDeleted(consdata->vars[v]) )
4219  {
4220  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4221  }
4222  }
4223  consdata->varsdeleted = FALSE;
4224  }
4225  }
4226 
4227  return SCIP_OKAY;
4228 }
4229 
4230 
4231 /** normalizes a linear constraint with the following rules:
4232  * - if all coefficients have them same absolute value, change them to (-)1.0
4233  * - multiplication with +1 or -1:
4234  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4235  * if the current rule doesn't determine the sign):
4236  * 1. the right hand side must not be negative
4237  * 2. the right hand side must not be infinite
4238  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4239  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4240  * 5. multiply with +1
4241  * - rationals to integrals
4242  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4243  * by the smallest common multiple of all denominators to get integral coefficients.
4244  * Forbid large denominators due to numerical stability.
4245  * - division by greatest common divisor
4246  * If all coefficients are integral, divide them by the greatest common divisor.
4247  */
4248 static
4250  SCIP* scip, /**< SCIP data structure */
4251  SCIP_CONS* cons, /**< linear constraint to normalize */
4252  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
4253  )
4254 {
4255  SCIP_CONSDATA* consdata;
4256  SCIP_Real* vals;
4257  SCIP_Longint scm;
4258  SCIP_Longint nominator;
4259  SCIP_Longint denominator;
4260  SCIP_Longint gcd;
4261  SCIP_Longint maxmult;
4262  SCIP_Real epsilon;
4263  SCIP_Real feastol;
4264  SCIP_Real maxabsval;
4265  SCIP_Real minabsval;
4266  SCIP_Bool success;
4267  SCIP_Bool onlyintegral;
4268  int nvars;
4269  int mult;
4270  int nposcoeffs;
4271  int nnegcoeffs;
4272  int i;
4273  int v;
4274 
4275  assert(scip != NULL);
4276  assert(cons != NULL);
4277  assert(infeasible != NULL);
4278 
4279  *infeasible = FALSE;
4280 
4281  /* we must not change a modifiable constraint in any way */
4282  if( SCIPconsIsModifiable(cons) )
4283  return SCIP_OKAY;
4284 
4285  /* get constraint data */
4286  consdata = SCIPconsGetData(cons);
4287  assert(consdata != NULL);
4288 
4289  /* check, if the constraint is already normalized */
4290  if( consdata->normalized )
4291  return SCIP_OKAY;
4292 
4293  /* get coefficient arrays */
4294  vals = consdata->vals;
4295  nvars = consdata->nvars;
4296  assert(nvars == 0 || vals != NULL);
4297 
4298  if( nvars == 0 )
4299  {
4300  consdata->normalized = TRUE;
4301  return SCIP_OKAY;
4302  }
4303 
4304  assert(vals != NULL);
4305 
4306  /* get maximal and minimal absolute coefficient */
4307  maxabsval = consdataGetMaxAbsval(consdata);
4308  minabsval = consdataGetMinAbsval(consdata);
4309 
4310  /* return if scaling by maxval will eliminate coefficients */
4311  if( SCIPisZero(scip, minabsval/maxabsval) )
4312  return SCIP_OKAY;
4313 
4314  /* check if all coefficients are in absolute value equal, and not 1.0 */
4315  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4316  {
4317  SCIP_Bool abscoefsequ;
4318 
4319  abscoefsequ = TRUE;
4320 
4321  for( v = nvars - 1; v >= 0; --v )
4322  {
4323  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4324  {
4325  abscoefsequ = FALSE;
4326  break;
4327  }
4328  }
4329 
4330  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4331  if( abscoefsequ )
4332  {
4333  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4334  SCIPdebugPrintCons(scip, cons, NULL);
4335  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4336 
4337  if( consdata->validmaxabsval )
4338  {
4339  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4340  consdata->maxabsval = 1.0;
4341  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4342  consdata->minabsval = 1.0;
4343 
4344  maxabsval = 1.0;
4345  }
4346  else
4347  {
4348  /* get maximal absolute coefficient */
4349  maxabsval = consdataGetMaxAbsval(consdata);
4350  }
4351 
4352  /* get new consdata information, because scaleCons() might have deleted variables */
4353  vals = consdata->vals;
4354  nvars = consdata->nvars;
4355 
4356  assert(nvars == 0 || vals != NULL);
4357  }
4358  }
4359 
4360  /* nvars might have changed */
4361  if( nvars == 0 )
4362  {
4363  consdata->normalized = TRUE;
4364  return SCIP_OKAY;
4365  }
4366 
4367  assert(vals != NULL);
4368 
4369  /* calculate the maximal multiplier for common divisor calculation:
4370  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4371  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4372  * additionally, we don't want to scale the constraint if this would lead to too
4373  * large coefficients
4374  */
4375  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4376  feastol = SCIPfeastol(scip);
4377  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4378 
4379  if( !consdata->hasnonbinvalid )
4380  consdataCheckNonbinvar(consdata);
4381 
4382  /* if all variables are of integral type we will allow a greater multiplier */
4383  if( !consdata->hascontvar )
4384  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4385  else
4386  maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4387 
4388  /*
4389  * multiplication with +1 or -1
4390  */
4391  mult = 0;
4392 
4393  /* 1. the right hand side must not be negative */
4394  if( SCIPisPositive(scip, consdata->lhs) )
4395  mult = +1;
4396  else if( SCIPisNegative(scip, consdata->rhs) )
4397  mult = -1;
4398 
4399  if( mult == 0 )
4400  {
4401  /* 2. the right hand side must not be infinite */
4402  if( SCIPisInfinity(scip, -consdata->lhs) )
4403  mult = +1;
4404  else if( SCIPisInfinity(scip, consdata->rhs) )
4405  mult = -1;
4406  }
4407 
4408  if( mult == 0 )
4409  {
4410  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4411  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4412  mult = +1;
4413  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4414  mult = -1;
4415  }
4416 
4417  if( mult == 0 )
4418  {
4419  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4420  nposcoeffs = 0;
4421  nnegcoeffs = 0;
4422  for( i = 0; i < nvars; ++i )
4423  {
4424  if( vals[i] > 0.0 )
4425  nposcoeffs++;
4426  else
4427  nnegcoeffs++;
4428  }
4429  if( nposcoeffs > nnegcoeffs )
4430  mult = +1;
4431  else if( nposcoeffs < nnegcoeffs )
4432  mult = -1;
4433  }
4434 
4435  if( mult == 0 )
4436  {
4437  /* 5. multiply with +1 */
4438  mult = +1;
4439  }
4440 
4441  assert(mult == +1 || mult == -1);
4442  if( mult == -1 )
4443  {
4444  /* scale the constraint with -1 */
4445  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4446  SCIPdebugPrintCons(scip, cons, NULL);
4447  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4448 
4449  /* scalecons() can delete variables, but scaling with -1 should not do that */
4450  assert(nvars == consdata->nvars);
4451  }
4452 
4453  /*
4454  * rationals to integrals
4455  *
4456  * @todo try scaling only on behalf of non-continuous variables
4457  */
4458  success = TRUE;
4459  scm = 1;
4460  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4461  {
4462  if( !SCIPisIntegral(scip, vals[i]) )
4463  {
4464  /* epsilon has been slightly decreased above - to be on the safe side */
4465  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4466  if( success )
4467  scm = SCIPcalcSmaComMul(scm, denominator);
4468  }
4469  }
4470  assert(scm >= 1);
4471 
4472  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4473  * their greatest common divisor
4474  */
4475  onlyintegral = TRUE;
4476  if( scm == 1 )
4477  {
4478  for( i = nvars - 1; i >= 0; --i )
4479  {
4480  if( !SCIPisIntegral(scip, vals[i]) )
4481  {
4482  onlyintegral = FALSE;
4483  break;
4484  }
4485  }
4486  }
4487 
4488  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4489  if( success && scm != 1 )
4490  {
4491  /* scale the constraint with the smallest common multiple of all denominators */
4492  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4493  SCIPdebugPrintCons(scip, cons, NULL);
4494  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4495 
4496  if( consdata->validmaxabsval )
4497  {
4498  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4499  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4500  {
4501  consdata->validmaxabsval = FALSE;
4502  consdata->maxabsval = SCIP_INVALID;
4503  consdataCalcMaxAbsval(consdata);
4504  }
4505  }
4506 
4507  if( consdata->validminabsval )
4508  {
4509  consdata->minabsval *= REALABS((SCIP_Real)scm);
4510  if( !SCIPisIntegral(scip, consdata->minabsval) )
4511  {
4512  consdata->validminabsval = FALSE;
4513  consdata->minabsval = SCIP_INVALID;
4514  consdataCalcMinAbsval(consdata);
4515  }
4516  }
4517 
4518  /* get new consdata information, because scalecons() might have deleted variables */
4519  vals = consdata->vals;
4520  nvars = consdata->nvars;
4521  assert(nvars == 0 || vals != NULL);
4522  }
4523 
4524  /*
4525  * division by greatest common divisor
4526  */
4527  if( success && nvars >= 1 )
4528  {
4529  /* all coefficients are integral: divide them by their greatest common divisor */
4530  assert(SCIPisIntegral(scip, vals[0]));
4531 
4532  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4533  for( i = 1; i < nvars && gcd > 1; ++i )
4534  {
4535  assert(SCIPisIntegral(scip, vals[i]));
4536  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4537  }
4538 
4539  if( gcd > 1 )
4540  {
4541  /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4542  if( !consdata->hascontvar && onlyintegral )
4543  {
4544  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4545  {
4546  *infeasible = TRUE;
4547 
4548  SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4549  SCIPdebugPrintCons(scip, cons, NULL);
4550 
4551  return SCIP_OKAY;
4552  }
4553  }
4554 
4555  /* divide the constraint by the greatest common divisor of the coefficients */
4556  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4557  SCIPdebugPrintCons(scip, cons, NULL);
4558  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4559 
4560  if( consdata->validmaxabsval )
4561  {
4562  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4563  }
4564  if( consdata->validminabsval )
4565  {
4566  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4567  }
4568  }
4569  }
4570 
4571  /* mark constraint to be normalized */
4572  consdata->normalized = TRUE;
4573 
4574  SCIPdebugMsg(scip, "normalized constraint:\n");
4575  SCIPdebugPrintCons(scip, cons, NULL);
4576 
4577  return SCIP_OKAY;
4578 }
4579 
4580 /** replaces multiple occurrences of a variable by a single coefficient */
4581 static
4583  SCIP* scip, /**< SCIP data structure */
4584  SCIP_CONS* cons /**< linear constraint */
4585  )
4586 {
4587  SCIP_CONSDATA* consdata;
4588  SCIP_VAR* var;
4589  SCIP_Real valsum;
4590  int v;
4591 
4592  assert(scip != NULL);
4593  assert(cons != NULL);
4594 
4595  consdata = SCIPconsGetData(cons);
4596  assert(consdata != NULL);
4597 
4598  if( consdata->merged )
4599  return SCIP_OKAY;
4600 
4601  /* sort the constraint */
4602  SCIP_CALL( consdataSort(scip, consdata) );
4603 
4604  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4605  * backward direction is necessary, since delCoefPos() modifies the given position and
4606  * the subsequent ones
4607  */
4608  v = consdata->nvars-1;
4609  while( v >= 1 )
4610  {
4611  var = consdata->vars[v];
4612  if( consdata->vars[v-1] == var )
4613  {
4614  valsum = consdata->vals[v];
4615  do
4616  {
4617  SCIP_CALL( delCoefPos(scip, cons, v) );
4618  --v;
4619  valsum += consdata->vals[v];
4620  }
4621  while( v >= 1 && consdata->vars[v-1] == var );
4622 
4623  /* modify the last existing occurrence of the variable */
4624  assert(consdata->vars[v] == var);
4625  if( SCIPisZero(scip, valsum) )
4626  {
4627  SCIP_CALL( delCoefPos(scip, cons, v) );
4628 
4629  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4630  * delta needs to be recalculated on the next real propagation
4631  */
4632  if( consdata->maxactdeltavar == var )
4633  {
4634  consdata->maxactdelta = SCIP_INVALID;
4635  consdata->maxactdeltavar = NULL;
4636  }
4637  }
4638  else
4639  {
4640  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4641  }
4642  }
4643  --v;
4644  }
4645 
4646  consdata->merged = TRUE;
4647 
4648  return SCIP_OKAY;
4649 }
4650 
4651 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4652 static
4654  SCIP* scip, /**< SCIP data structure */
4655  SCIP_CONS* cons, /**< linear constraint */
4656  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4657  * information is not needed; in this case, we apply all fixings
4658  * instead of stopping after the first infeasible one */
4659  )
4660 {
4661  SCIP_CONSDATA* consdata;
4662  SCIP_VAR* var;
4663  SCIP_VAR** aggrvars;
4664  SCIP_Real val;
4665  SCIP_Real* aggrscalars;
4666  SCIP_Real fixedval;
4667  SCIP_Real aggrconst;
4668  int v;
4669  int naggrvars;
4670  int i;
4671 
4672  assert(scip != NULL);
4673  assert(cons != NULL);
4674 
4675  if( infeasible != NULL )
4676  *infeasible = FALSE;
4677 
4678  consdata = SCIPconsGetData(cons);
4679  assert(consdata != NULL);
4680 
4681  if( consdata->eventdata == NULL )
4682  {
4683  SCIP_CONSHDLR* conshdlr;
4684  SCIP_CONSHDLRDATA* conshdlrdata;
4685 
4686  conshdlr = SCIPconsGetHdlr(cons);
4687  assert(conshdlr != NULL);
4688 
4689  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4690  assert(conshdlrdata != NULL);
4691 
4692  /* catch bound change events of variables */
4693  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4694  assert(consdata->eventdata != NULL);
4695  }
4696 
4697  if( !consdata->removedfixings )
4698  {
4699  SCIP_Real lhssubtrahend;
4700  SCIP_Real rhssubtrahend;
4701 
4702  /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4703  * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4704  */
4705  assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4706 
4707  lhssubtrahend = 0.0;
4708  rhssubtrahend = 0.0;
4709 
4710  SCIPdebugMsg(scip, "applying fixings:\n");
4711  SCIPdebugPrintCons(scip, cons, NULL);
4712 
4713  v = 0;
4714  while( v < consdata->nvars )
4715  {
4716  var = consdata->vars[v];
4717  val = consdata->vals[v];
4718  assert(SCIPvarIsTransformed(var));
4719 
4720  switch( SCIPvarGetStatus(var) )
4721  {
4723  SCIPerrorMessage("original variable in transformed linear constraint\n");
4724  return SCIP_INVALIDDATA;
4725 
4726  case SCIP_VARSTATUS_LOOSE:
4727  case SCIP_VARSTATUS_COLUMN:
4728  ++v;
4729  break;
4730 
4731  case SCIP_VARSTATUS_FIXED:
4732  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4733  fixedval = SCIPvarGetLbGlobal(var);
4734  if( !SCIPisInfinity(scip, -consdata->lhs) )
4735  {
4736  if( SCIPisInfinity(scip, ABS(fixedval)) )
4737  {
4738  if( val * fixedval > 0.0 )
4739  {
4740  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4741  }
4742  else
4743  {
4744  if( infeasible != NULL )
4745  {
4746  /* if lhs gets infinity it means that the problem is infeasible */
4747  *infeasible = TRUE;
4748  return SCIP_OKAY;
4749  }
4750  else
4751  {
4752  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4753  }
4754  }
4755  }
4756  else
4757  lhssubtrahend += val * fixedval;
4758  }
4759  if( !SCIPisInfinity(scip, consdata->rhs) )
4760  {
4761  if( SCIPisInfinity(scip, ABS(fixedval)) )
4762  {
4763  if( val * fixedval > 0.0 )
4764  {
4765  if( infeasible != NULL )
4766  {
4767  /* if rhs gets -infinity it means that the problem is infeasible */
4768  *infeasible = TRUE;
4769  return SCIP_OKAY;
4770  }
4771  else
4772  {
4773  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4774  }
4775  }
4776  else
4777  {
4778  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4779  }
4780  }
4781  else
4782  rhssubtrahend += val * fixedval;
4783  }
4784  SCIP_CALL( delCoefPos(scip, cons, v) );
4785  break;
4786 
4788  {
4789  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4790  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4791  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4792 
4793  assert(activevar != NULL);
4794  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4795  assert(activevar != NULL);
4796 
4797  if( !SCIPisZero(scip, activescalar) )
4798  {
4799  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4800  }
4801 
4802  if( !SCIPisZero(scip, activeconstant) )
4803  {
4804  if( !SCIPisInfinity(scip, -consdata->lhs) )
4805  lhssubtrahend += activeconstant;
4806  if( !SCIPisInfinity(scip, consdata->rhs) )
4807  rhssubtrahend += activeconstant;
4808  }
4809 
4810  SCIP_CALL( delCoefPos(scip, cons, v) );
4811  break;
4812  }
4815  naggrvars = SCIPvarGetMultaggrNVars(var);
4816  aggrvars = SCIPvarGetMultaggrVars(var);
4817  aggrscalars = SCIPvarGetMultaggrScalars(var);
4818  for( i = 0; i < naggrvars; ++i )
4819  {
4820  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4821  }
4822  aggrconst = SCIPvarGetMultaggrConstant(var);
4823 
4824  if( !SCIPisInfinity(scip, -consdata->lhs) )
4825  lhssubtrahend += val * aggrconst;
4826  if( !SCIPisInfinity(scip, consdata->rhs) )
4827  rhssubtrahend += val * aggrconst;
4828 
4829  SCIP_CALL( delCoefPos(scip, cons, v) );
4830  break;
4831 
4833  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4834  aggrconst = SCIPvarGetNegationConstant(var);
4835 
4836  if( !SCIPisInfinity(scip, -consdata->lhs) )
4837  lhssubtrahend += val * aggrconst;
4838  if( !SCIPisInfinity(scip, consdata->rhs) )
4839  rhssubtrahend += val * aggrconst;
4840 
4841  SCIP_CALL( delCoefPos(scip, cons, v) );
4842  break;
4843 
4844  default:
4845  SCIPerrorMessage("unknown variable status\n");
4846  SCIPABORT();
4847  return SCIP_INVALIDDATA; /*lint !e527*/
4848  }
4849  }
4850 
4851  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4852  {
4853  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4854  * causing wrong fixings of other variables --> better use a real zero here;
4855  * for small numbers, polishing the difference might lead to wrong results -->
4856  * better use the exact difference in this case
4857  */
4858  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4859  {
4860  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4861  }
4862  else
4863  {
4864  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4865  }
4866  }
4867  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4868  {
4869  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4870  * causing wrong fixings of other variables --> better use a real zero here;
4871  * for small numbers, polishing the difference might lead to wrong results -->
4872  * better use the exact difference in this case
4873  */
4874  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4875  {
4876  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4877  }
4878  else
4879  {
4880  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4881  }
4882  }
4883  consdata->removedfixings = TRUE;
4884 
4885  SCIPdebugMsg(scip, "after fixings:\n");
4886  SCIPdebugPrintCons(scip, cons, NULL);
4887 
4888  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4889  * to clean up the constraint
4890  */
4891  SCIP_CALL( mergeMultiples(scip, cons) );
4892 
4893  SCIPdebugMsg(scip, "after merging:\n");
4894  SCIPdebugPrintCons(scip, cons, NULL);
4895  }
4896  assert(consdata->removedfixings);
4897 
4898 #ifndef NDEBUG
4899  /* check, if all fixings are applied */
4900  for( v = 0; v < consdata->nvars; ++v )
4901  assert(SCIPvarIsActive(consdata->vars[v]));
4902 #endif
4903 
4904  return SCIP_OKAY;
4905 }
4906 
4907 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4908  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4909  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4910  * conflict detecting constraint by using NULL as inferred variable
4911  */
4912 static
4914  SCIP* scip, /**< SCIP data structure */
4915  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4916  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4917  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4918  int inferpos, /**< position of the inferred variable in the vars array */
4919  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4920  )
4921 {
4922  SCIP_CONSDATA* consdata;
4923  SCIP_VAR** vars;
4924  SCIP_Real* vals;
4925  int nvars;
4926  int i;
4927 
4928  assert(scip != NULL);
4929  assert(cons != NULL);
4930 
4931  consdata = SCIPconsGetData(cons);
4933  assert(consdata != NULL);
4934 
4935  vars = consdata->vars;
4936  vals = consdata->vals;
4937  nvars = consdata->nvars;
4938 
4939  assert(vars != NULL || nvars == 0);
4940  assert(vals != NULL || nvars == 0);
4941 
4942  assert(-1 <= inferpos && inferpos < nvars);
4943  assert((infervar == NULL) == (inferpos == -1));
4944  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4945 
4946  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4947  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4948  * - if the right hand side is the reason, the minimal residual activity is responsible
4949  * - if the left hand side is the reason, the maximal residual activity is responsible
4950  */
4951 
4952  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4953  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4954  {
4955  SCIP_Real minresactivity;
4956  SCIP_Real maxresactivity;
4957  SCIP_Bool minisrelax;
4958  SCIP_Bool maxisrelax;
4959  SCIP_Bool isminsettoinfinity;
4960  SCIP_Bool ismaxsettoinfinity;
4961 
4962  minresactivity = -SCIPinfinity(scip);
4963  maxresactivity = SCIPinfinity(scip);
4964 
4965  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4966  if( infervar != NULL )
4967  {
4968  assert(vals != NULL); /* for flexelint */
4969  if( reasonisrhs )
4970  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4971  &minisrelax, NULL, &isminsettoinfinity, NULL);
4972  else
4973  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4974  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4975  }
4976  else
4977  {
4978  if( reasonisrhs )
4979  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4980  &minisrelax, NULL, &isminsettoinfinity, NULL);
4981  else
4982  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4983  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4984  }
4985 
4986  /* we can only do something clever, if the residual activity is finite and not relaxed */
4987  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4988  {
4989  SCIP_Real rescap;
4990  SCIP_Bool resactisinf;
4991 
4992  resactisinf = FALSE;
4993 
4994  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4995  * than its inferred bound
4996  */
4997  if( infervar != NULL )
4998  {
4999  assert(vals != NULL); /* for flexelint */
5000 
5001  if( reasonisrhs )
5002  {
5003  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
5004  {
5005  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
5006  if( SCIPisInfinity(scip, -minresactivity) )
5007  resactisinf = TRUE;
5008  }
5009  rescap = consdata->rhs - minresactivity;
5010  }
5011  else
5012  {
5013  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
5014  {
5015  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
5016  if( SCIPisInfinity(scip, maxresactivity) )
5017  resactisinf = TRUE;
5018  }
5019  rescap = consdata->lhs - maxresactivity;
5020  }
5021 
5022  if( reasonisrhs == (vals[inferpos] > 0.0) )
5023  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
5024  else
5025  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5026  }
5027  else
5028  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5029 
5030  if( !resactisinf )
5031  {
5032  /* now add bounds as reasons until the residual capacity is exceeded */
5033  for( i = 0; i < nvars; ++i )
5034  {
5035  assert( vars != NULL && vals != NULL ); /* for lint */
5036 
5037  /* zero coefficients and the inferred variable can be ignored */
5038  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5039  continue;
5040 
5041  /* check if the residual capacity is exceeded */
5042  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5043  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5044  break;
5045 
5046  /* update the residual capacity due to the local bound of this variable */
5047  if( reasonisrhs == (vals[i] > 0.0) )
5048  {
5049  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5050  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5051  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5052  }
5053  else
5054  {
5055  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5056  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5057  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5058  }
5059  }
5060  return SCIP_OKAY;
5061  }
5062  }
5063  }
5064 
5065  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5066  for( i = 0; i < nvars; ++i )
5067  {
5068  assert(vars != NULL); /* for flexelint */
5069  assert(vals != NULL); /* for flexelint */
5070 
5071  /* zero coefficients and the inferred variable can be ignored */
5072  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5073  continue;
5074 
5075  if( reasonisrhs == (vals[i] > 0.0) )
5076  {
5077  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5078  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5079  }
5080  else
5081  {
5082  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5083  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5084  }
5085  }
5086 
5087  return SCIP_OKAY;
5088 }
5089 
5090 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5091  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5092  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5093  */
5094 static
5096  SCIP* scip, /**< SCIP data structure */
5097  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5098  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
5099  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5100  int inferpos /**< position of the inferred variable in the vars array, or -1 */
5101  )
5102 {
5103  SCIP_CONSDATA* consdata;
5104  SCIP_VAR** vars;
5105  int nvars;
5106  int v;
5107 
5108  assert(scip != NULL);
5109  assert(cons != NULL);
5110 
5111  consdata = SCIPconsGetData(cons);
5112  assert(consdata != NULL);
5113  vars = consdata->vars;
5114  nvars = consdata->nvars;
5115  assert(vars != NULL || nvars == 0);
5116  assert(-1 <= inferpos && inferpos < nvars);
5117  assert((infervar == NULL) == (inferpos == -1));
5118  assert(inferpos == -1 || vars != NULL);
5119  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5120 
5121  /* collect all fixed variables */
5122  for( v = nvars - 1; v >= 0; --v )
5123  {
5124  assert(vars != NULL); /* for flexelint */
5125 
5126  /* need to add old bounds before propagation of inferrence variable */
5127  if( vars[v] == infervar )
5128  {
5129  assert(vars[v] != NULL);
5130 
5131  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5132  {
5133  /* @todo get boundchange index before this last boundchange and correct the index */
5134  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5135  }
5136 
5137  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5138  {
5139  /* @todo get boundchange index before this last boundchange and correct the index */
5140  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5141  }
5142 
5143  continue;
5144  }
5145 
5146  /* check for fixed variables */
5147  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5148  {
5149  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5150  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5151  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5152  }
5153  }
5154 
5155  return SCIP_OKAY;
5156 }
5157 
5158 /** add reasoning variables to conflict candidate queue which led to the conflict */
5159 static
5161  SCIP* scip, /**< SCIP data structure */
5162  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5163  int nvars, /**< number of variables reasoning the infeasibility */
5164  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5165  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5166  )
5167 {
5168  int v;
5169 
5170  assert(scip != NULL);
5171 
5172  /* collect all variables for which the local bounds differ from their global bounds */
5173  for( v = nvars - 1; v >= 0; --v )
5174  {
5175  assert(vars != NULL);
5176 
5177  /* check for local bound changes variables */
5178  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5179  {
5180  /* add conflict bound */
5181  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5182  }
5183 
5184  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5185  {
5186  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5187  }
5188  }
5189 
5190  if( var != NULL )
5191  {
5192  if( bound < SCIPvarGetLbLocal(var) )
5193  {
5194  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5195  }
5196 
5197  if( bound > SCIPvarGetUbLocal(var) )
5198  {
5199  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5200  }
5201  }
5202 
5203  return SCIP_OKAY;
5204 }
5205 
5206 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5207  * propagation rule (see propagateCons()):
5208  * (1) activity residuals of all other variables tighten bounds of single variable
5209  */
5210 static
5212  SCIP* scip, /**< SCIP data structure */
5213  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5214  SCIP_VAR* infervar, /**< variable that was deduced */
5215  INFERINFO inferinfo, /**< inference information */
5216  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5217  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5218  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5219  )
5220 {
5221  SCIP_CONSDATA* consdata;
5222  SCIP_VAR** vars;
5223 #ifndef NDEBUG
5224  SCIP_Real* vals;
5225 #endif
5226  int nvars;
5227  int inferpos;
5228 
5229  assert(scip != NULL);
5230  assert(cons != NULL);
5231  assert(result != NULL);
5232 
5233  consdata = SCIPconsGetData(cons);
5234  assert(consdata != NULL);
5235  vars = consdata->vars;
5236  nvars = consdata->nvars;
5237 #ifndef NDEBUG
5238  vals = consdata->vals;
5239  assert(vars != NULL);
5240  assert(vals != NULL);
5241 #endif
5242 
5243  /* get the position of the inferred variable in the vars array */
5244  inferpos = inferInfoGetPos(inferinfo);
5245  if( inferpos >= nvars || vars[inferpos] != infervar )
5246  {
5247  /* find inference variable in constraint */
5248  /**@todo use a binary search here; the variables can be sorted by variable index */
5249  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5250  {}
5251  }
5252  assert(inferpos < nvars);
5253  assert(vars[inferpos] == infervar);
5254  assert(!SCIPisZero(scip, vals[inferpos]));
5255 
5256  switch( inferInfoGetProprule(inferinfo) )
5257  {
5258  case PROPRULE_1_RHS:
5259  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5260  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5261  * domain in order to not exceed the right hand side of the inequality
5262  */
5263  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5264  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5265  *result = SCIP_SUCCESS;
5266  break;
5267 
5268  case PROPRULE_1_LHS:
5269  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5270  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5271  * domain in order to not fall below the left hand side of the inequality
5272  */
5273  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5274  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5275  *result = SCIP_SUCCESS;
5276  break;
5277 
5278  case PROPRULE_1_RANGEDROW:
5279  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5280  * the given inference variable to their bounds in this given ranged row
5281  */
5282 
5283  /* check that we really have a ranged row here */
5284  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5285  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5286  *result = SCIP_SUCCESS;
5287  break;
5288 
5289  case PROPRULE_INVALID:
5290  default:
5291  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5292  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5293  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5294  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5295  SCIPinfoMessage(scip, NULL, ";\n");
5296  return SCIP_INVALIDDATA;
5297  }
5298 
5299  return SCIP_OKAY;
5300 }
5301 
5302 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5303 static
5305  SCIP* scip, /**< SCIP data structure */
5306  SCIP_CONS* cons, /**< conflict detecting constraint */
5307  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5308  )
5309 {
5310  /* conflict analysis can only be applied in solving stage and if it is turned on */
5312  return SCIP_OKAY;
5313 
5314  /* initialize conflict analysis */
5316 
5317  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5318  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5319 
5320  /* analyze the conflict */
5321  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5322 
5323  return SCIP_OKAY;
5324 }
5325 
5326 /** check if there is any hope of tightening some bounds */
5327 static
5329  SCIP_CONS* cons /**< linear constraint */
5330  )
5331 {
5332  SCIP_CONSDATA* consdata;
5333  int infcountmin;
5334  int infcountmax;
5335 
5336  consdata = SCIPconsGetData(cons);
5337  assert(consdata != NULL);
5338 
5339  infcountmin = consdata->minactivityneginf
5340  + consdata->minactivityposinf
5341  + consdata->minactivityneghuge
5342  + consdata->minactivityposhuge;
5343  infcountmax = consdata->maxactivityneginf
5344  + consdata->maxactivityposinf
5345  + consdata->maxactivityneghuge
5346  + consdata->maxactivityposhuge;
5348  if( infcountmin > 1 && infcountmax > 1 )
5349  return FALSE;
5350 
5351  return TRUE;
5352 }
5353 
5354 /** tighten upper bound */
5355 static
5357  SCIP* scip, /**< SCIP data structure */
5358  SCIP_CONS* cons, /**< linear constraint */
5359  int pos, /**< variable position */
5360  PROPRULE proprule, /**< propagation rule that deduced the value */
5361  SCIP_Real newub, /**< new upper bound */
5362  SCIP_Real oldub, /**< old upper bound */
5363  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5364  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5365  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5366  )
5367 {
5368  SCIP_CONSDATA* consdata;
5369  SCIP_VAR* var;
5370  SCIP_Real lb;
5371  SCIP_Bool infeasible;
5372  SCIP_Bool tightened;
5373 
5374  assert(cons != NULL);
5375  assert(!SCIPisInfinity(scip, newub));
5376 
5377  consdata = SCIPconsGetData(cons);
5378  assert(consdata != NULL);
5379  var = consdata->vars[pos];
5380  assert(var != NULL);
5381 
5382  lb = SCIPvarGetLbLocal(var);
5383  newub = SCIPadjustedVarUb(scip, var, newub);
5384 
5385  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5386  {
5387  SCIP_VARTYPE vartype;
5388 
5389  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5390  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos],
5391  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub);
5392 
5393  vartype = SCIPvarGetType(var);
5394 
5395  /* tighten upper bound */
5396  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5397 
5398  if( infeasible )
5399  {
5400  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5401  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5402 
5403  /* analyze conflict */
5404  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5405 
5406  *cutoff = TRUE;
5407  }
5408  else if( tightened )
5409  {
5410  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5411  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5412  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5413 
5414  (*nchgbds)++;
5415 
5416  /* if variable type was changed we might be able to upgrade the constraint */
5417  if( vartype != SCIPvarGetType(var) )
5418  consdata->upgradetried = FALSE;
5419  }
5420  }
5421  return SCIP_OKAY;
5422 }
5423 
5424 /** tighten lower bound */
5425 static
5427  SCIP* scip, /**< SCIP data structure */
5428  SCIP_CONS* cons, /**< linear constraint */
5429  int pos, /**< variable position */
5430  PROPRULE proprule, /**< propagation rule that deduced the value */
5431  SCIP_Real newlb, /**< new lower bound */
5432  SCIP_Real oldlb, /**< old lower bound */
5433  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5434  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5435  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5436  )
5437 {
5438  SCIP_CONSDATA* consdata;
5439  SCIP_VAR* var;
5440  SCIP_Real ub;
5441  SCIP_Bool infeasible;
5442  SCIP_Bool tightened;
5443 
5444  assert(cons != NULL);
5445  assert(!SCIPisInfinity(scip, newlb));
5446 
5447  consdata = SCIPconsGetData(cons);
5448  assert(consdata != NULL);
5449  var = consdata->vars[pos];
5450  assert(var != NULL);
5451 
5452  ub = SCIPvarGetUbLocal(var);
5453  newlb = SCIPadjustedVarLb(scip, var, newlb);
5454 
5455  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5456  {
5457  SCIP_VARTYPE vartype;
5458 
5459  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5460  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos],
5461  QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb);
5462 
5463  vartype = SCIPvarGetType(var);
5464 
5465  /* tighten lower bound */
5466  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5467 
5468  if( infeasible )
5469  {
5470  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5471  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5472 
5473  /* analyze conflict */
5474  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5475 
5476  *cutoff = TRUE;
5477  }
5478  else if( tightened )
5479  {
5480  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5481  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5482  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5483 
5484  (*nchgbds)++;
5485 
5486  /* if variable type was changed we might be able to upgrade the constraint */
5487  if( vartype != SCIPvarGetType(var) )
5488  consdata->upgradetried = FALSE;
5489  }
5490  }
5491  return SCIP_OKAY;
5492 }
5493 
5494 /** tightens bounds of a single variable due to activity bounds (easy case) */
5495 static
5497  SCIP* scip, /**< SCIP data structure */
5498  SCIP_CONS* cons, /**< linear constraint */
5499  int pos, /**< position of the variable in the vars array */
5500  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5501  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5502  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5503  )
5504 {
5505  SCIP_CONSDATA* consdata;
5506  SCIP_VAR* var;
5507  SCIP_Real val;
5508  SCIP_Real lb;
5509  SCIP_Real ub;
5510  SCIP_Real lhs;
5511  SCIP_Real rhs;
5512 
5513  assert(scip != NULL);
5514  assert(cons != NULL);
5515  assert(cutoff != NULL);
5516  assert(nchgbds != NULL);
5517 
5518  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5519  if( SCIPconsIsModifiable(cons) )
5520  return SCIP_OKAY;
5521 
5522  consdata = SCIPconsGetData(cons);
5523  assert(consdata != NULL);
5524  assert(0 <= pos && pos < consdata->nvars);
5525 
5526  *cutoff = FALSE;
5527 
5528  var = consdata->vars[pos];
5529  assert(var != NULL);
5530 
5531  /* we cannot tighten bounds of multi-aggregated variables */
5533  return SCIP_OKAY;
5534 
5535  val = consdata->vals[pos];
5536  lhs = consdata->lhs;
5537  rhs = consdata->rhs;
5538  assert(!SCIPisZero(scip, val));
5539  assert(!SCIPisInfinity(scip, lhs));
5540  assert(!SCIPisInfinity(scip, -rhs));
5541 
5542  lb = SCIPvarGetLbLocal(var);
5543  ub = SCIPvarGetUbLocal(var);
5544  assert(SCIPisLE(scip, lb, ub));
5545 
5546  /* recompute activities if needed */
5547  if( !consdata->validactivities )
5548  consdataCalcActivities(scip, consdata);
5549  assert(consdata->validactivities);
5550  if( !consdata->validminact )
5551  consdataRecomputeMinactivity(scip, consdata);
5552  assert(consdata->validminact);
5553 
5554  if( val > 0.0 )
5555  {
5556  /* check, if we can tighten the variable's upper bound */
5557  if( !SCIPisInfinity(scip, rhs) )
5558  {
5559  SCIP_Real slack;
5560  SCIP_Real alpha;
5561 
5562  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5563  assert(consdata->validminact);
5564 
5565  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5566  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5567  {
5568  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5569  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5570 
5571  *cutoff = TRUE;
5572  return SCIP_OKAY;
5573  }
5574 
5575  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5576 
5577  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5578  * it to zero
5579  */
5580  if( !SCIPisPositive(scip, slack) )
5581  slack = 0.0;
5582 
5583  alpha = val * (ub - lb);
5584  assert(!SCIPisNegative(scip, alpha));
5585 
5586  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5587  {
5588  SCIP_Real newub;
5589 
5590  /* compute new upper bound */
5591  newub = lb + (slack / val);
5592 
5593  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5594 
5595  if( *cutoff )
5596  {
5597  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5598  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5599 
5600  return SCIP_OKAY;
5601  }
5602 
5603  /* collect the new upper bound which is needed for the lower bound computation */
5604  ub = SCIPvarGetUbLocal(var);
5605  }
5606  }
5607 
5608  /* check, if we can tighten the variable's lower bound */
5609  if( !SCIPisInfinity(scip, -lhs) )
5610  {
5611  SCIP_Real slack;
5612  SCIP_Real alpha;
5613 
5614  /* make sure the max activity is reliable */
5615  if( !consdata->validmaxact )
5616  {
5617  consdataRecomputeMaxactivity(scip, consdata);
5618  }
5619  assert(consdata->validmaxact);
5620 
5621  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5622  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5623  {
5624  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5625  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5626 
5627  *cutoff = TRUE;
5628  return SCIP_OKAY;
5629  }
5630 
5631  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5632 
5633  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5634  * it to zero
5635  */
5636  if( !SCIPisPositive(scip, slack) )
5637  slack = 0.0;
5638 
5639  alpha = val * (ub - lb);
5640  assert(!SCIPisNegative(scip, alpha));
5641 
5642  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5643  {
5644  SCIP_Real newlb;
5645 
5646  /* compute new lower bound */
5647  newlb = ub - (slack / val);
5648 
5649  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5650 
5651  if( *cutoff )
5652  {
5653  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5654  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5655 
5656  return SCIP_OKAY;
5657  }
5658  }
5659  }
5660  }
5661  else
5662  {
5663  /* check, if we can tighten the variable's lower bound */
5664  if( !SCIPisInfinity(scip, rhs) )
5665  {
5666  SCIP_Real slack;
5667  SCIP_Real alpha;
5668 
5669  /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5670  assert(consdata->validminact);
5671 
5672  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5673  if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) )
5674  {
5675  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5676  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs);
5677 
5678  *cutoff = TRUE;
5679  return SCIP_OKAY;
5680  }
5681 
5682  slack = rhs - QUAD_TO_DBL(consdata->minactivity);
5683 
5684  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5685  * it to zero
5686  */
5687  if( !SCIPisPositive(scip, slack) )
5688  slack = 0.0;
5689 
5690  alpha = val * (lb - ub);
5691  assert(!SCIPisNegative(scip, alpha));
5692 
5693  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5694  {
5695  SCIP_Real newlb;
5696 
5697  /* compute new lower bound */
5698  newlb = ub + slack / val;
5699 
5700  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5701 
5702  if( *cutoff )
5703  {
5704  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5705  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5706 
5707  return SCIP_OKAY;
5708  }
5709  /* collect the new lower bound which is needed for the upper bound computation */
5710  lb = SCIPvarGetLbLocal(var);
5711  }
5712  }
5713 
5714  /* check, if we can tighten the variable's upper bound */
5715  if( !SCIPisInfinity(scip, -lhs) )
5716  {
5717  SCIP_Real slack;
5718  SCIP_Real alpha;
5719 
5720  /* make sure the max activity is reliable */
5721  if( !consdata->validmaxact )
5722  {
5723  consdataRecomputeMaxactivity(scip, consdata);
5724  }
5725  assert(consdata->validmaxact);
5726 
5727  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5728  if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) )
5729  {
5730  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5731  SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs);
5732 
5733  *cutoff = TRUE;
5734  return SCIP_OKAY;
5735  }
5736 
5737  slack = QUAD_TO_DBL(consdata->maxactivity) - lhs;
5738 
5739  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5740  * it to zero
5741  */
5742  if( !SCIPisPositive(scip, slack) )
5743  slack = 0.0;
5744 
5745  alpha = val * (lb - ub);
5746  assert(!SCIPisNegative(scip, alpha));
5747 
5748  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5749  {
5750  SCIP_Real newub;
5751 
5752  /* compute new upper bound */
5753  newub = lb - (slack / val);
5754 
5755  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5756 
5757  if( *cutoff )
5758  {
5759  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5760  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5761 
5762  return SCIP_OKAY;
5763  }
5764  }
5765  }
5766  }
5767 
5768  return SCIP_OKAY;
5769 }
5770 
5771 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5772 static
5774  SCIP* scip, /**< SCIP data structure */
5775  SCIP_CONS* cons, /**< conflict detecting constraint */
5776  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5777  int nvars, /**< number of variables reasoning the infeasibility */
5778  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5779  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5780  )
5781 {
5782 #ifndef NDEBUG
5783  SCIP_CONSDATA* consdata;
5784 
5785  assert(scip != NULL);
5786  assert(cons != NULL);
5787 
5788  consdata = SCIPconsGetData(cons);
5789  assert(consdata != NULL);
5790  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5791 #endif
5793  /* conflict analysis can only be applied in solving stage and if it is turned on */
5795  return SCIP_OKAY;
5796 
5797  /* initialize conflict analysis */
5799 
5800  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5801  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5802 
5803  /* add reasoning variables to conflict candidate queue which led to the conflict */
5804  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5805 
5806  /* analyze the conflict */
5807  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5808 
5809  return SCIP_OKAY;
5810 }
5811 
5812 /** propagate ranged rows
5813  *
5814  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5815  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5816  * variables better.
5817  *
5818  * Example:
5819  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5820  *
5821  * x3 needs to be a multiple of 3, so the instance is infeasible.
5822  *
5823  * Example:
5824  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5825  *
5826  * The only possible value for x3 is 2, so the variable will be fixed.
5827  *
5828  * @todo add holes if possible
5829  */
5830 static
5832  SCIP* scip, /**< SCIP data structure */
5833  SCIP_CONS* cons, /**< linear constraint */
5834  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5835  int* nfixedvars, /**< pointer to count number of fixed variables */
5836  int* nchgbds, /**< pointer to count the number of bound changes */
5837  int* naddconss /**< pointer to count number of added constraints */
5838  )
5839 {
5840  SCIP_CONSHDLRDATA* conshdlrdata;
5841  SCIP_CONSHDLR* conshdlr;
5842  SCIP_CONSDATA* consdata;
5843  SCIP_VAR** infcheckvars;
5844  SCIP_Real* infcheckvals;
5845  SCIP_Real minactinfvars;
5846  SCIP_Real maxactinfvars;
5847  SCIP_Real lb;
5848  SCIP_Real ub;
5849  SCIP_Real feastol;
5850  SCIP_Real fixedact;
5851  SCIP_Real lhs;
5852  SCIP_Real rhs;
5853  SCIP_Real absminbincoef;
5854  SCIP_Longint gcd;
5855  SCIP_Longint gcdtmp;
5856  SCIP_Bool minactinfvarsinvalid;
5857  SCIP_Bool maxactinfvarsinvalid;
5858  SCIP_Bool possiblegcd;
5859  SCIP_Bool gcdisone;
5860  SCIP_Bool addartconss;
5861  int ninfcheckvars;
5862  int nunfixedvars;
5863  int nfixedconsvars;
5864  int ncontvars;
5865  int pos;
5866  int v;
5867 
5868  assert(scip != NULL);
5869  assert(cons != NULL);
5870  assert(cutoff != NULL);
5871  assert(nfixedvars != NULL);
5872  assert(nchgbds != NULL);
5873  assert(naddconss != NULL);
5874 
5875  /* modifiable constraint can be changed so we do not have all necessary information */
5876  if( SCIPconsIsModifiable(cons) )
5877  return SCIP_OKAY;
5878 
5879  consdata = SCIPconsGetData(cons);
5880  assert(consdata != NULL);
5881 
5882  /* we already did full ranged row propagation */
5883  if( consdata->rangedrowpropagated == 2 )
5884  return SCIP_OKAY;
5885 
5886  /* at least three variables are needed */
5887  if( consdata->nvars < 3 )
5888  return SCIP_OKAY;
5889 
5890  /* do nothing on normal inequalities */
5891  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5892  return SCIP_OKAY;
5893 
5894  /* get constraint handler data */
5895  conshdlr = SCIPconsGetHdlr(cons);
5896  assert(conshdlr != NULL);
5897  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5898  assert(conshdlrdata != NULL);
5899 
5900  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5901 
5902  /* we may add artificial constraints */
5903  if( addartconss )
5904  consdata->rangedrowpropagated = 2;
5905  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5906  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5907  * artificial constraints
5908  */
5909  else
5910  {
5911  if( consdata->rangedrowpropagated > 0 )
5912  return SCIP_OKAY;
5913 
5914  consdata->rangedrowpropagated = 1;
5915  }
5916  fixedact = 0;
5917  nfixedconsvars = 0;
5918  /* calculate fixed activity and number of fixed variables */
5919  for( v = consdata->nvars - 1; v >= 0; --v )
5920  {
5921  /* all zero coefficients should be eliminated */
5922  assert(!SCIPisZero(scip, consdata->vals[v]));
5923 
5924  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5925  {
5926  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5927  ++nfixedconsvars;
5928  }
5929  }
5930 
5931  /* do not work with huge fixed activities */
5932  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5933  return SCIP_OKAY;
5934 
5935  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5936  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5937  lhs = consdata->lhs - fixedact;
5938  rhs = consdata->rhs - fixedact;
5939  nunfixedvars = consdata->nvars - nfixedconsvars;
5940 
5941  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5942  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5943  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5944 
5945  absminbincoef = SCIP_REAL_MAX;
5946  ncontvars = 0;
5947  gcdisone = TRUE;
5948  possiblegcd = TRUE;
5949 
5950  /* we now partition all unfixed variables in two groups:
5951  *
5952  * the first one contains all integral variable with integral
5953  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5954  * given
5955  *
5956  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5957  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5958  */
5959 
5960  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5961  * variables
5962  */
5963  ninfcheckvars = 0;
5964  v = -1;
5965  pos = -1;
5966  do
5967  {
5968  ++v;
5969 
5970  /* partition the variables, do not change the order of collection, because it might be used later on */
5971  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5972  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5973  {
5974  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5975  {
5976  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5977  {
5978  ++ncontvars;
5979  }
5980  else if( SCIPvarIsBinary(consdata->vars[v]) )
5981  {
5982  SCIP_Real absval;
5983 
5984  absval = REALABS(consdata->vals[v]);
5985 
5986  if( absminbincoef > absval )
5987  absminbincoef = absval;
5988  }
5989 
5990  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5991  possiblegcd = FALSE;
5992  infcheckvars[ninfcheckvars] = consdata->vars[v];
5993  infcheckvals[ninfcheckvars] = consdata->vals[v];
5994  ++ninfcheckvars;
5995 
5996  if( pos == -1 )
5997  pos = v;
5998  }
5999  ++v;
6000  }
6001  }
6002  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
6003 
6004  /* if the first group of variables is empty, we stop */
6005  /* @todo try to propagate/split up a constraint of the form:
6006  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
6007  * 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]
6008  */
6009  if( v == consdata->nvars )
6010  goto TERMINATE;
6011 
6012  /* we need at least two non-continuous variables */
6013  if( ncontvars + 2 > nunfixedvars )
6014  goto TERMINATE;
6015 
6016  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
6017  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
6018 
6019  feastol = SCIPfeastol(scip);
6020 
6021  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
6022  assert(gcd >= 2);
6023 
6024  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
6025  * calculate gcd over the first part of variables */
6026  for( ; v < consdata->nvars; ++v )
6027  {
6028  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6029  continue;
6030 
6031  if( SCIPvarIsBinary(consdata->vars[v]) )
6032  {
6033  SCIP_Real absval;
6034 
6035  absval = REALABS(consdata->vals[v]);
6036 
6037  if( absminbincoef > absval )
6038  absminbincoef = absval;
6039  }
6040 
6041  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6042  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6043  {
6044  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6045  ++ncontvars;
6046 
6047  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6048  possiblegcd = FALSE;
6049  infcheckvars[ninfcheckvars] = consdata->vars[v];
6050  infcheckvals[ninfcheckvars] = consdata->vals[v];
6051 
6052  ++ninfcheckvars;
6053 
6054  if( pos == -1 )
6055  pos = v;
6056  }
6057  else
6058  {
6059  assert(REALABS(consdata->vals[v]) > 1.5);
6060 
6061  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6062  assert(gcdtmp >= 1);
6063 
6064  if( gcdtmp == 1 )
6065  {
6066  infcheckvars[ninfcheckvars] = consdata->vars[v];
6067  infcheckvals[ninfcheckvars] = consdata->vals[v];
6068 
6069  ++ninfcheckvars;
6070 
6071  if( pos == -1 )
6072  pos = v;
6073  }
6074  else
6075  gcd = gcdtmp;
6076  }
6077  }
6078  assert(gcd >= 2);
6079 
6080  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6081  * normalizeCons() */
6082  if( ninfcheckvars == 0 )
6083  goto TERMINATE;
6084 
6085  assert(pos >= 0);
6086 
6087  minactinfvarsinvalid = FALSE;
6088  maxactinfvarsinvalid = FALSE;
6089  maxactinfvars = 0.0;
6090  minactinfvars = 0.0;
6091 
6092  /* calculate activities over all infcheckvars */
6093  for( v = ninfcheckvars - 1; v >= 0; --v )
6094  {
6095  lb = SCIPvarGetLbLocal(infcheckvars[v]);
6096  ub = SCIPvarGetUbLocal(infcheckvars[v]);
6097 
6098  if( SCIPisInfinity(scip, -lb) )
6099  {
6100  if( infcheckvals[v] < 0.0 )
6101  maxactinfvarsinvalid = TRUE;
6102  else
6103  minactinfvarsinvalid = TRUE;
6104  }
6105  else
6106  {
6107  if( infcheckvals[v] < 0.0 )
6108  maxactinfvars += infcheckvals[v] * lb;
6109  else
6110  minactinfvars += infcheckvals[v] * lb;
6111  }
6112 
6113  if( SCIPisInfinity(scip, ub) )
6114  {
6115  if( infcheckvals[v] > 0.0 )
6116  maxactinfvarsinvalid = TRUE;
6117  else
6118  minactinfvarsinvalid = TRUE;
6119  }
6120  else
6121  {
6122  if( infcheckvals[v] > 0.0 )
6123  maxactinfvars += infcheckvals[v] * ub;
6124  else
6125  minactinfvars += infcheckvals[v] * ub;
6126  }
6127 
6128  /* better abort on to big values */
6129  if( SCIPisHugeValue(scip, -minactinfvars) )
6130  minactinfvarsinvalid = TRUE;
6131  if( SCIPisHugeValue(scip, maxactinfvars) )
6132  maxactinfvarsinvalid = TRUE;
6133 
6134  if( minactinfvarsinvalid || maxactinfvarsinvalid )
6135  goto TERMINATE;
6136  }
6137  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6138 
6139  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6140  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6141 
6142  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6143  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6144  * activities */
6145  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6146  * !!!note!!!
6147  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6148  * are not at their global bound
6149  */
6150 
6151  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6152  * infeasibility */
6153  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6154  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6155  {
6156  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6157  SCIPdebugPrintCons(scip, cons, NULL);
6158 
6159  /* start conflict analysis */
6160  /* @todo improve conflict analysis by adding relaxed bounds */
6161  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6162 
6163  *cutoff = TRUE;
6164  }
6165  else if( ncontvars == 0 )
6166  {
6167  SCIP_Longint gcdinfvars = -1;
6168 
6169  /* check for gcd over all infcheckvars */
6170  if( possiblegcd )
6171  {
6172  v = ninfcheckvars - 1;
6173  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6174  assert(gcdinfvars >= 2);
6175 
6176  for( ; v >= 0 && gcdinfvars >= 2; --v )
6177  {
6178  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6179  }
6180  }
6181  else if( gcdisone )
6182  gcdinfvars = 1;
6183 
6184  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6185 
6186  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6187  if( gcdinfvars >= 1 )
6188  {
6189  SCIP_Real value;
6190  SCIP_Real value2;
6191  SCIP_Real minvalue = SCIP_INVALID;
6192  SCIP_Real maxvalue = SCIP_INVALID;
6193  int nsols = 0;
6194 
6195  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6196 
6197  /* check how many possible solutions exist */
6198  while( SCIPisLE(scip, value, maxactinfvars) )
6199  {
6200  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6201 
6202  /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6203  if( !SCIPisGE(scip, value2, lhs) )
6204  {
6205  value2 += gcd;
6206  }
6207 
6208  if( SCIPisLE(scip, value2, rhs) )
6209  {
6210  ++nsols;
6211 
6212  /* early termination if we found more than two solutions */
6213  if( nsols == 3 )
6214  break;
6215 
6216  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6217  minvalue = value;
6218 
6219  maxvalue = value;
6220  }
6221  value += gcdinfvars;
6222  }
6223  assert(nsols < 2 || minvalue <= maxvalue);
6224 
6225  /* determine last possible solution for better bounding */
6226  if( nsols == 3 )
6227  {
6228 #ifndef NDEBUG
6229  SCIP_Real secondsolval = maxvalue;
6230 #endif
6231  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6232 
6233  /* check how many possible solutions exist */
6234  while( SCIPisGE(scip, value, minactinfvars) )
6235  {
6236  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6237 
6238  /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6239  if( !SCIPisLE(scip, value2, rhs) )
6240  {
6241  value2 -= gcd;
6242  }
6243 
6244  if( SCIPisGE(scip, value2, lhs) )
6245  {
6246  maxvalue = value;
6247  assert(maxvalue > minvalue);
6248  break;
6249  }
6250  value -= gcdinfvars;
6251  }
6252  assert(maxvalue > secondsolval);
6253  }
6254 
6255  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6256  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6257 
6258  /* no possible solution found */
6259  if( nsols == 0 )
6260  {
6261  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6262  gcdinfvars, gcd, lhs, rhs);
6263  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6264  SCIPdebugPrintCons(scip, cons, NULL);
6265 
6266  /* start conflict analysis */
6267  /* @todo improve conflict analysis by adding relaxed bounds */
6268  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6269 
6270  *cutoff = TRUE;
6271  }
6272  /* if only one solution exist we can extract a new constraint or fix variables */
6273  else if( nsols == 1 )
6274  {
6275  assert(minvalue == maxvalue); /*lint !e777*/
6276 
6277  /* we can fix the only variable in our second set of variables */
6278  if( ninfcheckvars == 1 )
6279  {
6280  SCIP_Bool fixed;
6281 
6282  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6283 
6284  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6285  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6286  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6287 
6288  /* fix variable to only possible value */
6289  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6290  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6291 
6292  if( *cutoff )
6293  {
6294  /* start conflict analysis */
6295  /* @todo improve conflict analysis by adding relaxed bounds */
6296  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6297  }
6298 
6299  if( fixed )
6300  ++(*nfixedvars);
6301  }
6302  else
6303  {
6304  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6305  if( ninfcheckvars == nunfixedvars - 1 )
6306  {
6307  SCIP_Real bound;
6308  SCIP_Bool foundvar = FALSE;
6309  SCIP_Bool fixed;
6310  int w = 0;
6311 
6312  assert(ninfcheckvars > 0);
6313 
6314  /* find variable which is not an infcheckvar and fix it */
6315  for( v = 0; v < consdata->nvars - 1; ++v )
6316  {
6317  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6318  {
6319  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6320  {
6321 #ifndef NDEBUG
6322  int v2 = v + 1;
6323  int w2 = w;
6324 
6325  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6326 
6327  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6328  {
6329  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6330  continue;
6331 
6332  assert(consdata->vars[v2] == infcheckvars[w2]);
6333  ++w2;
6334  }
6335  assert(w2 == ninfcheckvars);
6336 #endif
6337  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6338 
6339  foundvar = TRUE;
6340 
6341  if( consdata->vals[v] < 0 )
6342  {
6343  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6344  }
6345  else
6346  {
6347  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6348  }
6349 
6350  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6351  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6352  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6353 
6354  /* fix variable to only possible value */
6355  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6356  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6357 
6358  if( *cutoff )
6359  {
6360  /* start conflict analysis */
6361  /* @todo improve conflict analysis by adding relaxed bounds */
6362  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6363  consdata->vars[v], bound) );
6364  }
6365 
6366  if( fixed )
6367  ++(*nfixedvars);
6368 
6369  break;
6370  }
6371 
6372  ++w;
6373  }
6374  }
6375 
6376  /* maybe last variable was the not infcheckvar */
6377  if( !foundvar )
6378  {
6379  assert(v == consdata->nvars - 1);
6380  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6381 
6382  if( consdata->vals[v] < 0 )
6383  {
6384  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6385  }
6386  else
6387  {
6388  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6389  }
6390 
6391  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6392  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6393  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6394 
6395  /* fix variable to only possible value */
6396  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6397  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6398 
6399  if( *cutoff )
6400  {
6401  /* start conflict analysis */
6402  /* @todo improve conflict analysis by adding relaxed bounds */
6403  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6404  consdata->vars[v], bound) );
6405  }
6406 
6407  if( fixed )
6408  ++(*nfixedvars);
6409  }
6410  }
6411  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6412  {
6413  /* aggregation possible if we have two variables, but this will be done later on */
6414  SCIP_CONS* newcons;
6415  char name[SCIP_MAXSTRLEN];
6416 
6417  /* create, add, and release new artificial constraint */
6418  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6419  ++conshdlrdata->naddconss;
6420 
6421  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6422 
6423  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6424  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6425  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6426 
6427  SCIPdebugPrintCons(scip, newcons, NULL);
6428 
6429  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6430 
6431  ++(*naddconss);
6432  }
6433  }
6434  }
6435  /* at least two solutions */
6436  else
6437  {
6438  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6439 
6440  /* only one variable in the second set, so we can bound this variables */
6441  if( ninfcheckvars == 1 )
6442  {
6443  SCIP_Bool tightened;
6444  SCIP_Real newlb;
6445  SCIP_Real newub;
6446 
6447  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6448 
6449  if( infcheckvals[0] < 0 )
6450  {
6451  newlb = maxvalue/infcheckvals[0];
6452  newub = minvalue/infcheckvals[0];
6453  }
6454  else
6455  {
6456  newlb = minvalue/infcheckvals[0];
6457  newub = maxvalue/infcheckvals[0];
6458  }
6459  assert(newlb < newub);
6460 
6461  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6462  {
6463  /* update lower bound of variable */
6464  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6465  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6466 
6467  /* tighten variable lower bound to minimal possible value */
6468  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6469  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6470 
6471  if( *cutoff )
6472  {
6473  /* start conflict analysis */
6474  /* @todo improve conflict analysis by adding relaxed bounds */
6475  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6476  }
6477 
6478  if( tightened )
6479  ++(*nchgbds);
6480  }
6481 
6482  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6483  {
6484  /* update upper bound of variable */
6485  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6486  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6487 
6488  /* tighten variable upper bound to maximal possible value */
6489  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6490  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6491 
6492  if( *cutoff )
6493  {
6494  /* start conflict analysis */
6495  /* @todo improve conflict analysis by adding relaxed bounds */
6496  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6497  }
6498 
6499  if( tightened )
6500  ++(*nchgbds);
6501  }
6502  }
6503  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6504  else if( ninfcheckvars == nunfixedvars - 1 )
6505  {
6506  SCIP_Bool foundvar = FALSE;
6507  SCIP_Bool tightened;
6508  SCIP_Real newlb;
6509  SCIP_Real newub;
6510  int w = 0;
6511 
6512  assert(ninfcheckvars > 0);
6513  assert(minvalue < maxvalue);
6514 
6515  /* find variable which is not an infcheckvar and fix it */
6516  for( v = 0; v < consdata->nvars - 1; ++v )
6517  {
6518  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6519  {
6520  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6521  {
6522 #ifndef NDEBUG
6523  int v2 = v + 1;
6524  int w2 = w;
6525 
6526  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6527 
6528  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6529  {
6530  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6531  continue;
6532 
6533  assert(consdata->vars[v2] == infcheckvars[w2]);
6534  ++w2;
6535  }
6536  assert(w2 == ninfcheckvars);
6537 #endif
6538 
6539  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6540  foundvar = TRUE;
6541 
6542  if( consdata->vals[v] < 0 )
6543  {
6544  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6545  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6546  }
6547  else
6548  {
6549  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6550  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6551  }
6552  assert(SCIPisLE(scip, newlb, newub));
6553 
6554  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6555  {
6556  /* update lower bound of variable */
6557  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6558  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6559 
6560  /* tighten variable lower bound to minimal possible value */
6561  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6562  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6563 
6564  if( *cutoff )
6565  {
6566  /* start conflict analysis */
6567  /* @todo improve conflict analysis by adding relaxed bounds */
6568  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6569  consdata->vars[v], newlb) );
6570  }
6571 
6572  if( tightened )
6573  ++(*nchgbds);
6574  }
6575 
6576  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6577  {
6578  /* update upper bound of variable */
6579  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6580  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6581 
6582  /* tighten variable upper bound to maximal possible value */
6583  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6584  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6585 
6586  if( *cutoff )
6587  {
6588  /* start conflict analysis */
6589  /* @todo improve conflict analysis by adding relaxed bounds */
6590  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6591  consdata->vars[v], newub) );
6592  }
6593 
6594  if( tightened )
6595  ++(*nchgbds);
6596  }
6597 
6598  break;
6599  }
6600 
6601  ++w;
6602  }
6603  }
6604 
6605  /* maybe last variable was the not infcheckvar */
6606  if( !foundvar )
6607  {
6608  assert(v == consdata->nvars - 1);
6609  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6610 
6611  if( consdata->vals[v] < 0 )
6612  {
6613  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6614  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6615  }
6616  else
6617  {
6618  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6619  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6620  }
6621  assert(SCIPisLE(scip, newlb, newub));
6622 
6623  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6624  {
6625  /* update lower bound of variable */
6626  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6627  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6628 
6629  /* tighten variable lower bound to minimal possible value */
6630  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6631  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6632 
6633  if( *cutoff )
6634  {
6635  /* start conflict analysis */
6636  /* @todo improve conflict analysis by adding relaxed bounds */
6637  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6638  }
6639 
6640  if( tightened )
6641  ++(*nchgbds);
6642  }
6643 
6644  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6645  {
6646  /* update upper bound of variable */
6647  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6648  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6649 
6650  /* tighten variable upper bound to maximal possible value */
6651  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6652  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6653 
6654  if( *cutoff )
6655  {
6656  /* start conflict analysis */
6657  /* @todo improve conflict analysis by adding relaxed bounds */
6658  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6659  }
6660 
6661  if( tightened )
6662  ++(*nchgbds);
6663  }
6664  }
6665  }
6666  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6667  * region for our infcheckvars, if possible
6668  */
6669  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6670  {
6671  SCIP_CONS* newcons;
6672  char name[SCIP_MAXSTRLEN];
6673  SCIP_Real newlhs;
6674  SCIP_Real newrhs;
6675 
6676  assert(maxvalue > minvalue);
6677 
6678  if( SCIPisGT(scip, minvalue, minactinfvars) )
6679  newlhs = minvalue;
6680  else
6681  newlhs = -SCIPinfinity(scip);
6682 
6683  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6684  newrhs = maxvalue;
6685  else
6686  newrhs = SCIPinfinity(scip);
6687 
6688  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6689  {
6690  /* create, add, and release new artificial constraint */
6691  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6692  ++conshdlrdata->naddconss;
6693 
6694  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6695 
6696  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6697  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6698  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6699 
6700  SCIPdebugPrintCons(scip, newcons, NULL);
6701  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6702 
6703  ++(*naddconss);
6704  }
6705  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6706  * should be maxvalue */
6707  }
6708  }
6709  }
6710  }
6711  else if( addartconss && ncontvars < ninfcheckvars )
6712  {
6713  SCIP_Real maxact = 0.0;
6714  SCIP_Real minact = 0.0;
6715  int w = 0;
6716 
6717  /* compute activities of non-infcheckvars */
6718  for( v = 0; v < consdata->nvars; ++v )
6719  {
6720  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6721  {
6722  ++w;
6723  continue;
6724  }
6725 
6726  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6727  {
6728  if( SCIPvarIsBinary(consdata->vars[v]) )
6729  {
6730  if( consdata->vals[v] > 0.0 )
6731  maxact += consdata->vals[v];
6732  else
6733  minact += consdata->vals[v];
6734  }
6735  else
6736  {
6737  SCIP_Real tmpval;
6738 
6739  assert(SCIPvarIsIntegral(consdata->vars[v]));
6740 
6741  if( consdata->vals[v] > 0.0 )
6742  {
6743  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6744 
6745  if( SCIPisHugeValue(scip, -tmpval) )
6746  break;
6747 
6748  minact += tmpval;
6749 
6750  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6751 
6752  if( SCIPisHugeValue(scip, tmpval) )
6753  break;
6754 
6755  maxact += tmpval;
6756  }
6757  else
6758  {
6759  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6760 
6761  if( SCIPisHugeValue(scip, -tmpval) )
6762  break;
6763 
6764  minact += tmpval;
6765 
6766  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6767 
6768  if( SCIPisHugeValue(scip, tmpval) )
6769  break;
6770 
6771  maxact += tmpval;
6772  }
6773  }
6774  }
6775  }
6776  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6777  {
6778  SCIP_CONS* newcons;
6779  char name[SCIP_MAXSTRLEN];
6780  SCIP_Real newlhs;
6781  SCIP_Real newrhs;
6782 
6783  assert(maxact > minact);
6784  assert(w == ninfcheckvars);
6785 
6786  newlhs = lhs - maxact;
6787  newrhs = rhs - minact;
6788  assert(newlhs < newrhs);
6789 
6790  /* create, add, and release new artificial constraint */
6791  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6792  ++conshdlrdata->naddconss;
6793 
6794  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6795 
6796  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6797  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6798  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6799 
6800  SCIPdebugPrintCons(scip, newcons, NULL);
6801  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6802 
6803  ++(*naddconss);
6804  }
6805  }
6806 
6807  TERMINATE:
6808  SCIPfreeBufferArray(scip, &infcheckvals);
6809  SCIPfreeBufferArray(scip, &infcheckvars);
6810 
6811  return SCIP_OKAY;
6812 }
6813 
6814 /** tightens bounds of a single variable due to activity bounds */
6815 static
6817  SCIP* scip, /**< SCIP data structure */
6818  SCIP_CONS* cons, /**< linear constraint */
6819  int pos, /**< position of the variable in the vars array */
6820  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6821  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6822  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6823  )
6824 {
6825  SCIP_CONSDATA* consdata;
6826  SCIP_VAR* var;
6827  SCIP_Real val;
6828  SCIP_Real lb;
6829  SCIP_Real ub;
6830  SCIP_Real minresactivity;
6831  SCIP_Real maxresactivity;
6832  SCIP_Real lhs;
6833  SCIP_Real rhs;
6834  SCIP_Bool infeasible;
6835  SCIP_Bool tightened;
6836  SCIP_Bool minisrelax;
6837  SCIP_Bool maxisrelax;
6838  SCIP_Bool isminsettoinfinity;
6839  SCIP_Bool ismaxsettoinfinity;
6840 
6841  assert(scip != NULL);
6842  assert(cons != NULL);
6843  assert(cutoff != NULL);
6844  assert(nchgbds != NULL);
6845 
6846  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6847  if( SCIPconsIsModifiable(cons) )
6848  return SCIP_OKAY;
6849 
6850  consdata = SCIPconsGetData(cons);
6851  assert(consdata != NULL);
6852  assert(0 <= pos && pos < consdata->nvars);
6853 
6854  *cutoff = FALSE;
6855 
6856  var = consdata->vars[pos];
6857 
6858  /* we cannot tighten bounds of multi-aggregated variables */
6860  return SCIP_OKAY;
6861 
6862  val = consdata->vals[pos];
6863  lhs = consdata->lhs;
6864  rhs = consdata->rhs;
6865  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6866  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6867  assert(var != NULL);
6868  assert(!SCIPisZero(scip, val));
6869  assert(!SCIPisInfinity(scip, lhs));
6870  assert(!SCIPisInfinity(scip, -rhs));
6871 
6872  lb = SCIPvarGetLbLocal(var);
6873  ub = SCIPvarGetUbLocal(var);
6874  assert(SCIPisLE(scip, lb, ub));
6875 
6876  if( val > 0.0 )
6877  {
6878  /* check, if we can tighten the variable's bounds */
6879  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6880  {
6881  SCIP_Real newub;
6882 
6883  newub = (rhs - minresactivity)/val;
6884 
6885  if( !SCIPisInfinity(scip, newub) &&
6886  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6887  {
6888  SCIP_Bool activityunreliable;
6889  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6890 
6891  /* check minresactivities for reliability */
6892  if( activityunreliable )
6893  {
6894  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6895  newub = (rhs - minresactivity)/val;
6896  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6897  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6898  && (!force || !SCIPisLT(scip, newub, ub)));
6899  }
6900 
6901  if( !activityunreliable )
6902  {
6903  /* tighten upper bound */
6904  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6905  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6906  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, 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), lb, newub);
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  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6922  assert(SCIPisFeasLE(scip, ub, newub));
6923  (*nchgbds)++;
6924 
6925  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6926  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6927  }
6928  }
6929  }
6930  }
6931 
6932  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6933  {
6934  SCIP_Real newlb;
6935 
6936  newlb = (lhs - maxresactivity)/val;
6937  if( !SCIPisInfinity(scip, -newlb) &&
6938  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6939  {
6940  /* check maxresactivities for reliability */
6941  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6942  {
6943  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6944  newlb = (lhs - maxresactivity)/val;
6945 
6946  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6947  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6948  && (!force || !SCIPisGT(scip, newlb, lb))) )
6949  return SCIP_OKAY;
6950  }
6951 
6952  /* tighten lower bound */
6953  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6954  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6955  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6956  &infeasible, &tightened) );
6957  if( infeasible )
6958  {
6959  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6960  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6961 
6962  /* analyze conflict */
6963  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6964 
6965  *cutoff = TRUE;
6966  return SCIP_OKAY;
6967  }
6968  if( tightened )
6969  {
6970  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6971  assert(SCIPisFeasGE(scip, lb, newlb));
6972  (*nchgbds)++;
6973  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6974  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6975  }
6976  }
6977  }
6978  }
6979  else
6980  {
6981  /* check, if we can tighten the variable's bounds */
6982  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6983  {
6984  SCIP_Real newlb;
6985 
6986  newlb = (rhs - minresactivity)/val;
6987  if( !SCIPisInfinity(scip, -newlb) &&
6988  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6989  {
6990  SCIP_Bool activityunreliable;
6991  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6992  /* check minresactivities for reliability */
6993  if( activityunreliable )
6994  {
6995  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6996  newlb = (rhs - minresactivity)/val;
6997 
6998  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6999  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
7000  && (!force || !SCIPisGT(scip, newlb, lb)));
7001  }
7002 
7003  if( !activityunreliable )
7004  {
7005  /* tighten lower bound */
7006  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
7007  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
7008  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
7009  &infeasible, &tightened) );
7010  if( infeasible )
7011  {
7012  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7013  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
7014 
7015  /* analyze conflict */
7016  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7017 
7018  *cutoff = TRUE;
7019  return SCIP_OKAY;
7020  }
7021  if( tightened )
7022  {
7023  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7024  assert(SCIPisFeasGE(scip, lb, newlb));
7025  (*nchgbds)++;
7026  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7027  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7028  }
7029  }
7030  }
7031  }
7032 
7033  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7034  {
7035  SCIP_Real newub;
7036 
7037  newub = (lhs - maxresactivity)/val;
7038  if( !SCIPisInfinity(scip, newub) &&
7039  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7040  {
7041  /* check maxresactivities for reliability */
7042  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7043  {
7044  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7045  newub = (lhs - maxresactivity)/val;
7046 
7047  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7048  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7049  && (!force || !SCIPisLT(scip, newub, ub))) )
7050  return SCIP_OKAY;
7051  }
7052 
7053  /* tighten upper bound */
7054  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7055  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7056  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7057  &infeasible, &tightened) );
7058  if( infeasible )
7059  {
7060  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
7061  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7062 
7063  /* analyze conflict */
7064  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7065 
7066  *cutoff = TRUE;
7067  return SCIP_OKAY;
7068  }
7069  if( tightened )
7070  {
7071  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7072  assert(SCIPisFeasLE(scip, ub, newub));
7073  (*nchgbds)++;
7074  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7075  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7076  }
7077  }
7078  }
7079  }
7080 
7081  return SCIP_OKAY;
7082 }
7083 
7084 #define MAXTIGHTENROUNDS 10
7085 
7086 /** tightens bounds of variables in constraint due to activity bounds */
7087 static
7089  SCIP* scip, /**< SCIP data structure */
7090  SCIP_CONS* cons, /**< linear constraint */
7091  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7092  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7093  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7094  int* nchgbds /**< pointer to count the total number of tightened bounds */
7095  )
7096 {
7097  SCIP_CONSDATA* consdata;
7098  unsigned int tightenmode;
7099  int nvars;
7100  int nrounds;
7101  int lastchange;
7102  int oldnchgbds;
7103 #ifndef SCIP_DEBUG
7104  int oldnchgbdstotal;
7105 #endif
7106  int v;
7107  SCIP_Bool force;
7108  SCIP_Bool easycase;
7109 
7110  assert(scip != NULL);
7111  assert(cons != NULL);
7112  assert(nchgbds != NULL);
7113  assert(cutoff != NULL);
7114 
7115  *cutoff = FALSE;
7116 
7117  /* we cannot tighten variables' bounds, if the constraint may be not complete */
7118  if( SCIPconsIsModifiable(cons) )
7119  return SCIP_OKAY;
7120 
7121  /* if a constraint was created after presolve, then it may hold fixed variables
7122  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7123  * thus, ensure here again that variable fixings have been applied
7124  */
7125  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7126  if( *cutoff )
7127  return SCIP_OKAY;
7128 
7129  /* check if constraint has any chances of tightening bounds */
7130  if( !canTightenBounds(cons) )
7131  return SCIP_OKAY;
7132 
7133  consdata = SCIPconsGetData(cons);
7134  assert(consdata != NULL);
7135 
7136  nvars = consdata->nvars;
7137  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7138 
7139  /* we are at the root node or during presolving */
7140  if( SCIPgetDepth(scip) < 1 )
7141  tightenmode = 2;
7142  else
7143  tightenmode = 1;
7144 
7145  /* stop if we already tightened the constraint and the tightening is not forced */
7146  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7147  return SCIP_OKAY;
7148 
7149  /* ensure that the variables are properly sorted */
7150  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7151  {
7152  SCIP_CALL( consdataSort(scip, consdata) );
7153  assert(consdata->coefsorted);
7154  }
7155 
7156  /* update maximal activity delta if necessary */
7157  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7158  consdataRecomputeMaxActivityDelta(scip, consdata);
7159 
7160  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7161  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7162  checkMaxActivityDelta(scip, consdata);
7163 
7164  /* this may happen if all variables are fixed */
7165  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7166  return SCIP_OKAY;
7167 
7168  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7169  {
7170  SCIP_Real slack;
7171  SCIP_Real surplus;
7172  SCIP_Real minactivity;
7173  SCIP_Real maxactivity;
7174  SCIP_Bool minisrelax;
7175  SCIP_Bool maxisrelax;
7176  SCIP_Bool isminsettoinfinity;
7177  SCIP_Bool ismaxsettoinfinity;
7178 
7179  /* use maximal activity delta to skip propagation (cannot deduce anything) */
7180  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7181  &isminsettoinfinity, &ismaxsettoinfinity);
7182  assert(!SCIPisInfinity(scip, minactivity));
7183  assert(!SCIPisInfinity(scip, -maxactivity));
7184 
7185  slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7186  surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7187 
7188  /* check if the constraint will propagate */
7189  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7190  return SCIP_OKAY;
7191  }
7192 
7193  /* check if we can use fast implementation for easy and numerically well behaved cases */
7194  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7195 
7196  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7197  lastchange = -1;
7198  oldnchgbds = 0;
7199 
7200 #ifndef SCIP_DEBUG
7201  oldnchgbdstotal = *nchgbds;
7202 #endif
7203 
7204  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7205  {
7206  /* ensure that the variables are properly sorted
7207  *
7208  * note: it might happen that integer variables become binary during bound tightening at the root node
7209  */
7210  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7211  {
7212  SCIP_CALL( consdataSort(scip, consdata) );
7213  assert(consdata->coefsorted);
7214  }
7215 
7216  /* mark the constraint to have the variables' bounds tightened */
7217  consdata->boundstightened = (unsigned int)tightenmode;
7218 
7219  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7220  * sorting enables skipping variables
7221  */
7222  v = 0;
7223  while( v < nvars && v != lastchange && !(*cutoff) )
7224  {
7225  oldnchgbds = *nchgbds;
7226 
7227  if( easycase )
7228  {
7229  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7230  }
7231  else
7232  {
7233  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7234  }
7235 
7236  /* if there was no progress, skip the rest of the binary variables */
7237  if( *nchgbds > oldnchgbds )
7238  {
7239  lastchange = v;
7240  ++v;
7241  }
7242  else if( consdata->coefsorted && v < consdata->nbinvars - 1
7243  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7244  v = consdata->nbinvars;
7245  else
7246  ++v;
7247  }
7248 
7249 #ifndef SCIP_DEBUG
7250  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7251  *nchgbds - oldnchgbdstotal, nrounds);
7252  oldnchgbdstotal += oldnchgbds;
7253 #endif
7254  }
7255 
7256 #ifndef NDEBUG
7257  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7258  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7259 #endif
7260 
7261  return SCIP_OKAY;
7262 }
7263 
7264 /** checks linear constraint for feasibility of given solution or current solution */
7265 static
7267  SCIP* scip, /**< SCIP data structure */
7268  SCIP_CONS* cons, /**< linear constraint */
7269  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7270  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7271  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7272  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7273  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7274  )
7275 {
7276  SCIP_CONSDATA* consdata;
7277  SCIP_Real activity;
7278  SCIP_Real absviol;
7279  SCIP_Real relviol;
7280  SCIP_Real lhsviol;
7281  SCIP_Real rhsviol;
7282 
7283  assert(scip != NULL);
7284  assert(cons != NULL);
7285  assert(violated != NULL);
7286 
7287  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7288  SCIPdebugPrintCons(scip, cons, NULL);
7289 
7290  consdata = SCIPconsGetData(cons);
7291  assert(consdata != NULL);
7292 
7293  *violated = FALSE;
7294 
7295  if( consdata->row != NULL )
7296  {
7297  if( !checklprows && SCIProwIsInLP(consdata->row) )
7298  return SCIP_OKAY;
7299  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7300  activity = consdataComputePseudoActivity(scip, consdata);
7301  else
7302  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7303  }
7304  else
7305  activity = consdataGetActivity(scip, consdata, sol);
7306 
7307  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7308  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7309  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7310  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7311 
7312  /* calculate absolute and relative bound violations */
7313  lhsviol = consdata->lhs - activity;
7314  rhsviol = activity - consdata->rhs;
7315 
7316  absviol = 0.0;
7317  relviol = 0.0;
7318  if( (lhsviol > 0) && (lhsviol > rhsviol) )
7319  {
7320  absviol = lhsviol;
7321  relviol = SCIPrelDiff(consdata->lhs, activity);
7322  }
7323  else if( rhsviol > 0 )
7324  {
7325  absviol = rhsviol;
7326  relviol = SCIPrelDiff(activity, consdata->rhs);
7327  }
7328 
7329  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7330  * return infeasible for safety
7331  */
7332  if( activity == SCIP_INVALID ) /*lint !e777*/
7333  {
7334  assert(sol == NULL);
7335  *violated = TRUE;
7336 
7337  /* set violation of invalid pseudo solutions */
7338  absviol = SCIP_INVALID;
7339  relviol = SCIP_INVALID;
7340 
7341  /* reset constraint age since we are in enforcement */
7342  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7343  }
7344  /* check with relative tolerances (the default) */
7345  else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7346  {
7347  /* the "normal" check: one of the two sides is violated */
7348  if( !checkrelmaxabs )
7349  {
7350  *violated = TRUE;
7351 
7352  /* only reset constraint age if we are in enforcement */
7353  if( sol == NULL )
7354  {
7355  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7356  }
7357  }
7358  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7359  * small compared to the absolute values occurring in the activity
7360  */
7361  else
7362  {
7363  SCIP_Real maxabs;
7364  SCIP_Real coef;
7365  SCIP_Real absval;
7366  SCIP_Real solval;
7367  int v;
7368 
7369  maxabs = 1.0;
7370 
7371  /* compute maximum absolute value */
7372  for( v = 0; v < consdata->nvars; ++v )
7373  {
7374  if( consdata->vals != NULL )
7375  {
7376  coef = consdata->vals[v];
7377  }
7378  else
7379  coef = 1.0;
7380 
7381  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7382  absval = REALABS( coef * solval );
7383  maxabs = MAX( maxabs, absval );
7384  }
7385 
7386  /* regard left hand side, first */
7387  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7388  {
7389  /* check whether violation is random noise */
7390  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7391  {
7392  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7393  consdata->lhs - activity, maxabs);
7394  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7395 
7396  /* only increase constraint age if we are in enforcement */
7397  if( sol == NULL )
7398  {
7399  SCIP_CALL( SCIPincConsAge(scip, cons) );
7400  }
7401  }
7402  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7403  else if( SCIPisZero(scip, consdata->lhs) )
7404  {
7405  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7406  {
7407  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7408  consdata->lhs - activity, maxabs);
7409  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7410 
7411  /* only increase constraint age if we are in enforcement */
7412  if( sol == NULL )
7413  {
7414  SCIP_CALL( SCIPincConsAge(scip, cons) );
7415  }
7416  }
7417  else
7418  {
7419  *violated = TRUE;
7420 
7421  /* only reset constraint age if we are in enforcement */
7422  if( sol == NULL )
7423  {
7424  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7425  }
7426  }
7427  }
7428  else
7429  {
7430  *violated = TRUE;
7431 
7432  /* only reset constraint age if we are in enforcement */
7433  if( sol == NULL )
7434  {
7435  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7436  }
7437  }
7438  }
7439 
7440  /* now regard right hand side */
7441  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7442  {
7443  /* check whether violation is random noise */
7444  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7445  {
7446  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7447  activity - consdata->rhs, maxabs);
7448  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7449 
7450  /* only increase constraint age if we are in enforcement */
7451  if( sol == NULL )
7452  {
7453  SCIP_CALL( SCIPincConsAge(scip, cons) );
7454  }
7455  }
7456  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7457  else if( SCIPisZero(scip, consdata->rhs) )
7458  {
7459  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7460  {
7461  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7462  activity - consdata->rhs, maxabs);
7463  SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7464 
7465  /* only increase constraint age if we are in enforcement */
7466  if( sol == NULL )
7467  {
7468  SCIP_CALL( SCIPincConsAge(scip, cons) );
7469  }
7470  }
7471  else
7472  {
7473  *violated = TRUE;
7474 
7475  /* only reset constraint age if we are in enforcement */
7476  if( sol == NULL )
7477  {
7478  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7479  }
7480  }
7481  }
7482  else
7483  {
7484  *violated = TRUE;
7485 
7486  /* only reset constraint age if we are in enforcement */
7487  if( sol == NULL )
7488  {
7489  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7490  }
7491  }
7492  }
7493  }
7494  }
7495  /* check with absolute tolerances */
7496  else if( consdata->checkabsolute &&
7497  ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7498  (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7499  {
7500  *violated = TRUE;
7501 
7502  /* only reset constraint age if we are in enforcement */
7503  if( sol == NULL )
7504  {
7505  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7506  }
7507  }
7508  else
7509  {
7510  /* only increase constraint age if we are in enforcement */
7511  if( sol == NULL )
7512  {
7513  SCIP_CALL( SCIPincConsAge(scip, cons) );
7514  }
7515  }
7516 
7517  /* update absolute and relative violation of the solution */
7518  if( sol != NULL )
7519  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7520 
7521  return SCIP_OKAY;
7522 }
7523 
7524 /** creates an LP row in a linear constraint data */
7525 static
7527  SCIP* scip, /**< SCIP data structure */
7528  SCIP_CONS* cons /**< linear constraint */
7529  )
7530 {
7531  SCIP_CONSDATA* consdata;
7532 
7533  assert(scip != NULL);
7534  assert(cons != NULL);
7535 
7536  consdata = SCIPconsGetData(cons);
7537  assert(consdata != NULL);
7538  assert(consdata->row == NULL);
7539 
7540  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7542 
7543  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7544 
7545  return SCIP_OKAY;
7546 }
7547 
7548 /** adds linear constraint as cut to the LP */
7549 static
7551  SCIP* scip, /**< SCIP data structure */
7552  SCIP_CONS* cons, /**< linear constraint */
7553  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7554  )
7555 {
7556  SCIP_CONSDATA* consdata;
7557 
7558  assert(scip != NULL);
7559  assert(cons != NULL);
7560 
7561  consdata = SCIPconsGetData(cons);
7562  assert(consdata != NULL);
7563 
7564  if( consdata->row == NULL )
7565  {
7566  if( !SCIPconsIsModifiable(cons) )
7567  {
7568  /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP
7569  * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7570  */
7571  SCIP_CALL( applyFixings(scip, cons, cutoff) );
7572  if( *cutoff )
7573  return SCIP_OKAY;
7574  }
7575 
7576  /* convert consdata object into LP row */
7577  SCIP_CALL( createRow(scip, cons) );
7578  }
7579  assert(consdata->row != NULL);
7580 
7581  if( consdata->nvars == 0 )
7582  {
7583  SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7584  }
7585 
7586  /* insert LP row as cut */
7587  if( !SCIProwIsInLP(consdata->row) )
7588  {
7589  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7590  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7591  /* if presolving is turned off, the row might be trivial */
7592  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7593  {
7594  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7595  }
7596 #ifndef NDEBUG
7597  else
7598  {
7599  int pr;
7600  int cr;
7601  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7602  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7603  assert( pr == 0 || cr == 0 );
7604  }
7605 #endif
7606  }
7607 
7608  return SCIP_OKAY;
7609 }
7610 
7611 /** adds linear constraint as row to the NLP, if not added yet */
7612 static
7614  SCIP* scip, /**< SCIP data structure */
7615  SCIP_CONS* cons /**< linear constraint */
7616  )
7617 {
7618  SCIP_CONSDATA* consdata;
7619 
7620  assert(SCIPisNLPConstructed(scip));
7621 
7622  /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
7623  if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
7624  return SCIP_OKAY;
7625 
7626  consdata = SCIPconsGetData(cons);
7627  assert(consdata != NULL);
7628 
7629  if( consdata->nlrow == NULL )
7630  {
7631  assert(consdata->lhs <= consdata->rhs);
7633  SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
7634  0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
7635 
7636  assert(consdata->nlrow != NULL);
7637  }
7638 
7639  if( !SCIPnlrowIsInNLP(consdata->nlrow) )
7640  {
7641  SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
7642  }
7643 
7644  return SCIP_OKAY;
7645 }
7646 
7647 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7648 static
7650  SCIP* scip, /**< SCIP data structure */
7651  SCIP_CONS* cons, /**< linear constraint */
7652  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7653  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7654  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7655  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7656  * the ones with non-zero dual value? */
7657  int* ncuts, /**< pointer to add up the number of found cuts */
7658  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7659  )
7660 {
7661  SCIP_CONSDATA* consdata;
7662  SCIP_Bool violated;
7663  int oldncuts;
7664 
7665  assert(scip != NULL);
7666  assert(conshdlrdata != NULL);
7667  assert(cons != NULL);
7668  assert(cutoff != NULL);
7669 
7670  consdata = SCIPconsGetData(cons);
7671  assert(ncuts != NULL);
7672  assert(consdata != NULL);
7673 
7674  oldncuts = *ncuts;
7675  *cutoff = FALSE;
7676 
7677  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7678 
7679  if( violated )
7680  {
7681  /* insert LP row as cut */
7682  SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7683  (*ncuts)++;
7684  }
7685  else if( !SCIPconsIsModifiable(cons) && separatecards )
7686  {
7687  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7688  if( !separateall && sol == NULL )
7689  {
7690  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7691  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7692  {
7693  SCIP_Real dualsol;
7694 
7695  dualsol = SCIProwGetDualsol(consdata->row);
7696  if( SCIPisFeasNegative(scip, dualsol) )
7697  {
7698  if( !SCIPisInfinity(scip, consdata->rhs) )
7699  {
7700  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7701  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7702  }
7703  }
7704  else if( SCIPisFeasPositive(scip, dualsol) )
7705  {
7706  if( !SCIPisInfinity(scip, -consdata->lhs) )
7707  {
7708  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7709  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7710  }
7711  }
7712  }
7713  }
7714  else
7715  {
7716  if( !SCIPisInfinity(scip, consdata->rhs) )
7717  {
7718  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7719  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7720  }
7721  if( !SCIPisInfinity(scip, -consdata->lhs) )
7722  {
7723  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7724  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7725  }
7726  }
7727  }
7728 
7729  if( *ncuts > oldncuts )
7730  {
7731  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7732  }
7733 
7734  return SCIP_OKAY;
7735 }
7736 
7737 /** propagation method for linear constraints */
7738 static
7740  SCIP* scip, /**< SCIP data structure */
7741  SCIP_CONS* cons, /**< linear constraint */
7742  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7743  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7744  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7745  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7746  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7747  int* nchgbds /**< pointer to count the total number of tightened bounds */
7748  )
7749 {
7750  SCIP_CONSDATA* consdata;
7751  SCIP_Real minactivity;
7752  SCIP_Real maxactivity;
7753  SCIP_Bool minactisrelax;
7754  SCIP_Bool maxactisrelax;
7755  SCIP_Bool isminsettoinfinity;
7756  SCIP_Bool ismaxsettoinfinity;
7757 
7758  assert(scip != NULL);
7759  assert(cons != NULL);
7760  assert(cutoff != NULL);
7761  assert(nchgbds != NULL);
7762 
7763  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7764 
7765  consdata = SCIPconsGetData(cons);
7766  assert(consdata != NULL);
7767 
7768  if( consdata->eventdata == NULL )
7769  {
7770  SCIP_CONSHDLR* conshdlr;
7771  SCIP_CONSHDLRDATA* conshdlrdata;
7772 
7773  conshdlr = SCIPconsGetHdlr(cons);
7774  assert(conshdlr != NULL);
7775 
7776  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7777  assert(conshdlrdata != NULL);
7778 
7779  /* catch bound change events of variables */
7780  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7781  assert(consdata->eventdata != NULL);
7782  }
7783 
7784  *cutoff = FALSE;
7785 
7786  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7787  if( !SCIPconsIsModifiable(cons) )
7788  {
7789  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7790  if( !SCIPinRepropagation(scip) )
7791  {
7792  SCIP_CALL( SCIPincConsAge(scip, cons) );
7793  }
7794 
7795  /* tighten the variable's bounds */
7796  if( tightenbounds )
7797  {
7798  int oldnchgbds;
7799 
7800  oldnchgbds = *nchgbds;
7801 
7802  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7803 
7804  if( *nchgbds > oldnchgbds )
7805  {
7806  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7807  }
7808  }
7809 
7810  /* propagate ranged rows */
7811  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7812  {
7813  int nfixedvars;
7814  int naddconss;
7815  SCIPdebug( int oldnchgbds = *nchgbds; )
7816 
7817  nfixedvars = 0;
7818  naddconss = 0;
7819 
7820  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7821 
7822  if( *cutoff )
7823  {
7824  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7825  }
7826  else
7827  {
7828  SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7829  }
7830 
7831  if( nfixedvars > 0 )
7832  *nchgbds += 2*nfixedvars;
7833  } /*lint !e438*/
7834 
7835  /* check constraint for infeasibility and redundancy */
7836  if( !(*cutoff) )
7837  {
7838  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7839  &isminsettoinfinity, &ismaxsettoinfinity);
7840 
7841  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7842  {
7843  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7844  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7845 
7846  /* analyze conflict */
7847  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7848 
7849  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7850  *cutoff = TRUE;
7851  }
7852  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7853  {
7854  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7855  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7856 
7857  /* analyze conflict */
7858  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7859 
7860  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7861  *cutoff = TRUE;
7862  }
7863  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7864  {
7865  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7866  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7867 
7868  /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7869  if( consdata->nvars > 0 )
7870  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7871  else
7872  SCIP_CALL( SCIPdelCons(scip, cons) );
7873  }
7874  }
7875  }
7876 
7877  return SCIP_OKAY;
7878 }
7879 
7880 
7881 /*
7882  * Presolving methods
7883  */
7884 
7885 /** converts all variables with fixed domain into FIXED variables */
7886 static
7888  SCIP* scip, /**< SCIP data structure */
7889  SCIP_CONS* cons, /**< linear constraint */
7890  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7891  int* nfixedvars /**< pointer to count the total number of fixed variables */
7892  )
7893 {
7894  SCIP_CONSDATA* consdata;
7895  SCIP_VAR* var;
7896  SCIP_VARSTATUS varstatus;
7897  SCIP_Real lb;
7898  SCIP_Real ub;
7899  SCIP_Bool fixed;
7900  SCIP_Bool infeasible;
7901  int v;
7902 
7903  assert(scip != NULL);
7904  assert(cons != NULL);
7905  assert(cutoff != NULL);
7906  assert(nfixedvars != NULL);
7907 
7908  consdata = SCIPconsGetData(cons);
7909  assert(consdata != NULL);
7910 
7911  for( v = 0; v < consdata->nvars; ++v )
7912  {
7913  assert(consdata->vars != NULL);
7914  var = consdata->vars[v];
7915  varstatus = SCIPvarGetStatus(var);
7916 
7917  if( varstatus != SCIP_VARSTATUS_FIXED )
7918  {
7919  lb = SCIPvarGetLbGlobal(var);
7920  ub = SCIPvarGetUbGlobal(var);
7921  if( SCIPisEQ(scip, lb, ub) )
7922  {
7923  SCIP_Real fixval;
7924 
7925  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7926  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7927  SCIPvarGetName(var), lb, ub, fixval);
7928  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7929  if( infeasible )
7930  {
7931  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7932  *cutoff = TRUE;
7933  return SCIP_OKAY;
7934  }
7935  if( fixed )
7936  (*nfixedvars)++;
7937  }
7938  }
7939  }
7940 
7941  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7942 
7943  if( infeasible )
7944  {
7945  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7946  *cutoff = TRUE;
7947  return SCIP_OKAY;
7948  }
7949 
7950  assert(consdata->removedfixings);
7951 
7952  return SCIP_OKAY;
7953 }
7954 
7955 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7956 
7957 /** extracts cliques of the constraint and adds them to SCIP
7958  *
7959  * The following clique extraction mechanism are implemeneted
7960  *
7961  * 1. collect binary variables and sort them in non increasing order, then
7962  *
7963  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7964  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7965  * condition
7966  *
7967  * minactivity + vals[i] + vals[i+1] > rhs
7968  *
7969  * and also add the binary to binary implication also for non-successive variables for which the same argument
7970  * holds
7971  *
7972  * minactivity + vals[i] + vals[j] > rhs
7973  *
7974  * 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
7975  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7976  *
7977  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7978  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7979  * condition
7980  *
7981  * maxactivity + vals[i] + vals[i-1] < lhs
7982  *
7983  * and also add the binary to binary implication also for non-successive variables for which the same argument
7984  * holds
7985  *
7986  * maxactivity + vals[i] + vals[j] < lhs
7987  *
7988  * e.g. you could multiply the above example by -1
7989  *
7990  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7991  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7992  * condition
7993  *
7994  * minactivity - vals[i] - vals[i-1] > rhs
7995  *
7996  * and also add the binary to binary implication also for non-successive variables for which the
7997  * same argument holds
7998  *
7999  * minactivity - vals[i] - vals[j] > rhs
8000  *
8001  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
8002  * implication x1 = 0 => x3 = 1
8003  *
8004  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
8005  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
8006  * condition
8007  *
8008  * maxactivity - vals[i] - vals[i+1] < lhs
8009  *
8010  * and also add the binary to binary implication also for non-successive variables for which the same argument
8011  * holds
8012  *
8013  * maxactivity - vals[i] - vals[j] < lhs
8014  *
8015  * e.g. you could multiply the above example by -1
8016  *
8017  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
8018  * as clique, (this part is done at the end of the method)
8019  *
8020  */
8021 static
8023  SCIP* scip, /**< SCIP data structure */
8024  SCIP_CONS* cons, /**< linear constraint */
8025  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
8026  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
8027  int* nfixedvars, /**< pointer to count number of fixed variables */
8028  int* nchgbds, /**< pointer to count the total number of tightened bounds */
8029  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
8030  )
8031 {
8032  SCIP_VAR** vars;
8033  SCIP_Real* vals;
8034  SCIP_CONSDATA* consdata;
8035  SCIP_Bool lhsclique;
8036  SCIP_Bool rhsclique;
8037  SCIP_Bool finitelhs;
8038  SCIP_Bool finiterhs;
8039  SCIP_Bool finiteminact;
8040  SCIP_Bool finitemaxact;
8041  SCIP_Bool finitenegminact;
8042  SCIP_Bool finitenegmaxact;
8043  SCIP_Bool finiteposminact;
8044  SCIP_Bool finiteposmaxact;
8045  SCIP_Bool infeasible;
8046  SCIP_Bool stopped;
8047  int cliquenonzerosadded;
8048  int v;
8049  int i;
8050  int nposcoefs;
8051  int nnegcoefs;
8052  int nvars;
8053 
8054  assert(scip != NULL);
8055  assert(cons != NULL);
8056  assert(nfixedvars != NULL);
8057  assert(nchgbds != NULL);
8058  assert(cutoff != NULL);
8059  assert(!SCIPconsIsDeleted(cons));
8060 
8061  consdata = SCIPconsGetData(cons);
8062  assert(consdata != NULL);
8063 
8064  if( consdata->nvars < 2 )
8065  return SCIP_OKAY;
8066 
8067  /* add implications if posibble
8068  *
8069  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8070  * maximal absolute contribution and also only if this variable would force all other variables to their bound
8071  * corresponding to the global minimal activity of the constraint
8072  */
8073  if( !consdata->implsadded )
8074  {
8075  /* sort variables by variable type */
8076  SCIP_CALL( consdataSort(scip, consdata) );
8077 
8078  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8079  * up front, might change sorting correspondingly
8080  */
8081  /* fast abort if no binaries exist */
8082  if( !SCIPvarIsBinary(consdata->vars[0]) )
8083  {
8084 #ifndef NDEBUG
8085  for( i = 1; i < consdata->nvars; i++ )
8086  assert(!SCIPvarIsBinary(consdata->vars[i]));
8087 #endif
8088  return SCIP_OKAY;
8089  }
8090  nvars = consdata->nvars;
8091  vars = consdata->vars;
8092  vals = consdata->vals;
8093 
8094  /* recompute activities if needed */
8095  if( !consdata->validactivities )
8096  consdataCalcActivities(scip, consdata);
8097  assert(consdata->validactivities);
8098 
8099  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8100  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8101  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8102  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8103  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8104  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8105  finiteminact = (finitenegminact && finiteposminact);
8106  finitemaxact = (finitenegmaxact && finiteposmaxact);
8107 
8108  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8109  {
8110  SCIP_Real maxabscontrib = -1.0;
8111  SCIP_Bool posval = FALSE;
8112  SCIP_Bool allbinary = TRUE;
8113  int oldnchgbds = *nchgbds;
8114  int nbdchgs = 0;
8115  int nimpls = 0;
8116  int position = -1;
8117 
8118  /* we need a valid minimal/maximal activity to add cliques */
8119  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8120  {
8121  consdataRecomputeGlbMinactivity(scip, consdata);
8122  assert(consdata->validglbminact);
8123  }
8124 
8125  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8126  {
8127  consdataRecomputeGlbMaxactivity(scip, consdata);
8128  assert(consdata->validglbmaxact);
8129  }
8130  assert(consdata->validglbminact || consdata->validglbmaxact);
8131 
8132  /* @todo extend this to local/constraint probing */
8133 
8134  /* determine maximal contribution to the activity */
8135  for( v = nvars - 1; v >= 0; --v )
8136  {
8137  if( SCIPvarIsBinary(vars[v]) )
8138  {
8139  if( vals[v] > 0 )
8140  {
8141  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8142 
8143  if( value > maxabscontrib )
8144  {
8145  maxabscontrib = value;
8146  position = v;
8147  posval = TRUE;
8148  }
8149  }
8150  else
8151  {
8152  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8153 
8154  value = REALABS(value);
8155 
8156  if( value > maxabscontrib )
8157  {
8158  maxabscontrib = value;
8159  position = v;
8160  posval = FALSE;
8161  }
8162  }
8163  }
8164  else
8165  allbinary = FALSE;
8166  }
8167  assert(0 <= position && position < nvars);
8168 
8169  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8170  {
8171  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8172  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8173  * implications
8174  */
8175  if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) )
8176  {
8177  for( v = nvars - 1; v >= 0; --v )
8178  {
8179  /* binary to binary implications will be collected when extrating cliques */
8180  if( !SCIPvarIsBinary(vars[v]) )
8181  {
8182  if( v != position )
8183  {
8184  if( vals[v] > 0 )
8185  {
8186  /* add implications */
8187  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8188  ++nimpls;
8189  *nchgbds += nbdchgs;
8190  }
8191  else
8192  {
8193  /* add implications */
8194  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8195  ++nimpls;
8196  *nchgbds += nbdchgs;
8197  }
8198 
8199  if( infeasible )
8200  {
8201  *cutoff = TRUE;
8202  break;
8203  }
8204  }
8205  }
8206  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8207  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8208  break;
8209  }
8210  }
8211 
8212  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8213  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8214  * implications
8215  */
8216  if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) )
8217  {
8218  for( v = nvars - 1; v >= 0; --v )
8219  {
8220  /* binary to binary implications will be collected when extrating cliques */
8221  if( !SCIPvarIsBinary(vars[v]) )
8222  {
8223  if( v != position )
8224  {
8225  if( vals[v] > 0 )
8226  {
8227  /* add implications */
8228  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8229  ++nimpls;
8230  *nchgbds += nbdchgs;
8231  }
8232  else
8233  {
8234  /* add implications */
8235  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8236  ++nimpls;
8237  *nchgbds += nbdchgs;
8238  }
8239 
8240  if( infeasible )
8241  {
8242  *cutoff = TRUE;
8243  break;
8244  }
8245  }
8246  }
8247  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8248  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8249  break;
8250  }
8251  }
8252 
8253  /* did we find some implications */
8254  if( nimpls > 0 )
8255  {
8256  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8257 
8258  if( *cutoff )
8259  return SCIP_OKAY;
8260 
8261  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8262  if( *nchgbds - oldnchgbds > 0 )
8263  {
8264  /* check for fixed variables */
8265  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8266  if( *cutoff )
8267  return SCIP_OKAY;
8268 
8269  /* tighten variable's bounds */
8270  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8271  if( *cutoff )
8272  return SCIP_OKAY;
8273 
8274  /* check for fixed variables */
8275  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8276  if( *cutoff )
8277  return SCIP_OKAY;
8278  }
8279  }
8280  }
8281  }
8282 
8283  consdata->implsadded = TRUE;
8284  }
8285 
8286  /* check if we already added the cliques of this constraint */
8287  if( consdata->cliquesadded )
8288  return SCIP_OKAY;
8289 
8290  consdata->cliquesadded = TRUE;
8291  cliquenonzerosadded = 0;
8292  stopped = FALSE;
8293 
8294  /* sort variables by variable type */
8295  SCIP_CALL( consdataSort(scip, consdata) );
8296 
8297  nvars = consdata->nvars;
8298  vars = consdata->vars;
8299  vals = consdata->vals;
8300 
8301  /**@todo extract more cliques, implications and variable bounds from linear constraints */
8302 
8303  /* recompute activities if needed */
8304  if( !consdata->validactivities )
8305  consdataCalcActivities(scip, consdata);
8306  assert(consdata->validactivities);
8307 
8308  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8309  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8310  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8311  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8312  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8313  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8314  finiteminact = (finitenegminact && finiteposminact);
8315  finitemaxact = (finitenegmaxact && finiteposmaxact);
8316 
8317  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8318  * information
8319  */
8320  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8321  {
8322  SCIP_VAR** binvars;
8323  SCIP_Real* binvarvals;
8324  int nposbinvars = 0;
8325  int nnegbinvars = 0;
8326  int allonebinary = 0;
8327 
8328  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8329  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8330 
8331  /* collect binary variables */
8332  for( i = 0; i < nvars; ++i )
8333  {
8334  if( SCIPvarIsBinary(vars[i]) )
8335  {
8336  assert(!SCIPisZero(scip, vals[i]));
8337 
8338  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8339  ++allonebinary;
8340 
8341  binvars[nposbinvars + nnegbinvars] = vars[i];
8342  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8343 
8344  if( SCIPisPositive(scip, vals[i]) )
8345  ++nposbinvars;
8346  else
8347  ++nnegbinvars;
8348 
8349  assert(nposbinvars + nnegbinvars <= nvars);
8350  }
8351  /* stop searching for binary variables, because the constraint data is sorted */
8352  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8353  break;
8354  }
8355  assert(nposbinvars + nnegbinvars <= nvars);
8356 
8357  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8358  * cliques
8359  */
8360  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8361  {
8362  SCIP_Real threshold;
8363  int oldnchgbds = *nchgbds;
8364  int nbdchgs;
8365  int jstart;
8366  int j;
8367 
8368  /* we need a valid minimal/maximal activity to add cliques */
8369  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8370  {
8371  consdataRecomputeGlbMinactivity(scip, consdata);
8372  assert(consdata->validglbminact);
8373  }
8374 
8375  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8376  {
8377  consdataRecomputeGlbMaxactivity(scip, consdata);
8378  assert(consdata->validglbmaxact);
8379  }
8380  assert(consdata->validglbminact || consdata->validglbmaxact);
8381 
8382  /* sort coefficients non-increasing to be faster in the clique search */
8383  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8384 
8385  /* case a) */
8386  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8387  {
8388  /* compute value that needs to be exceeded */
8389  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8390 
8391  j = 1;
8392 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8393  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8394  assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8395 #endif
8396  /* check if at least two variables are in a clique */
8397  if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8398  {
8399  ++j;
8400  /* check for extending the clique */
8401  while( j < nposbinvars )
8402  {
8403  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8404  break;
8405  ++j;
8406  }
8407  assert(j >= 2);
8408 
8409  /* add clique with at least two variables */
8410  SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8411 
8412  if( infeasible )
8413  *cutoff = TRUE;
8414 
8415  *nchgbds += nbdchgs;
8416 
8417  cliquenonzerosadded += j;
8418  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8419  stopped = TRUE;
8420 
8421  /* exchange the last variable in the clique if possible and add all new ones */
8422  if( !stopped && !(*cutoff) && j < nposbinvars )
8423  {
8424  SCIP_VAR** clqvars;
8425  int lastfit = j - 2;
8426  assert(lastfit >= 0);
8427 
8428  /* copy all 'main'-clique variables */
8429  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8430 
8431  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8432  while( lastfit >= 0 && j < nposbinvars )
8433  {
8434  /* check if two variables are in a clique */
8435  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8436  {
8437  clqvars[lastfit + 1] = binvars[j];
8438 
8439  /* add clique with at least two variables */
8440  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8441 
8442  if( infeasible )
8443  {
8444  *cutoff = TRUE;
8445  break;
8446  }
8447 
8448  *nchgbds += nbdchgs;
8449 
8450  cliquenonzerosadded += (lastfit + 2);
8451  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8452  {
8453  stopped = TRUE;
8454  break;
8455  }
8456 
8457  ++j;
8458  }
8459  else
8460  --lastfit;
8461  }
8462 
8463  SCIPfreeBufferArray(scip, &clqvars);
8464  }
8465  }
8466  }
8467 
8468  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8469  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8470  {
8471  /* check for fixed variables */
8472  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8473 
8474  if( !*cutoff )
8475  {
8476  /* tighten variable's bounds */
8477  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8478 
8479  if( !*cutoff )
8480  {
8481  /* check for fixed variables */
8482  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8483 
8484  if( !*cutoff )
8485  {
8486  /* sort variables by variable type */
8487  SCIP_CALL( consdataSort(scip, consdata) );
8488 
8489  /* recompute activities if needed */
8490  if( !consdata->validactivities )
8491  consdataCalcActivities(scip, consdata);
8492  assert(consdata->validactivities);
8493 
8494  nvars = consdata->nvars;
8495  vars = consdata->vars;
8496  vals = consdata->vals;
8497  nposbinvars = 0;
8498  nnegbinvars = 0;
8499  allonebinary = 0;
8500 
8501  /* update binary variables */
8502  for( i = 0; i < nvars; ++i )
8503  {
8504  if( SCIPvarIsBinary(vars[i]) )
8505  {
8506  assert(!SCIPisZero(scip, vals[i]));
8507 
8508  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8509  ++allonebinary;
8510 
8511  binvars[nposbinvars + nnegbinvars] = vars[i];
8512  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8513 
8514  if( SCIPisPositive(scip, vals[i]) )
8515  ++nposbinvars;
8516  else
8517  ++nnegbinvars;
8518 
8519  assert(nposbinvars + nnegbinvars <= nvars);
8520  }
8521  /* stop searching for binary variables, because the constraint data is sorted */
8522  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8523  break;
8524  }
8525  assert(nposbinvars + nnegbinvars <= nvars);
8526  }
8527  }
8528  }
8529 
8530  oldnchgbds = *nchgbds;
8531  }
8532 
8533  /* case b) */
8534  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8535  {
8536  /* compute value that needs to be deceeded */
8537  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8538 
8539  i = nposbinvars + nnegbinvars - 1;
8540  j = i - 1;
8541 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8542  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8543  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8544 #endif
8545  /* check if two variables are in a clique */
8546  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8547  {
8548  --j;
8549  /* check for extending the clique */
8550  while( j >= nposbinvars )
8551  {
8552  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8553  break;
8554  --j;
8555  }
8556  jstart = j;
8557 
8558  assert(i - j >= 2);
8559  /* add clique with at least two variables */
8560  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8561 
8562  if( infeasible )
8563  *cutoff = TRUE;
8564 
8565  *nchgbds += nbdchgs;
8566 
8567  cliquenonzerosadded += (i - j);
8568  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8569  stopped = TRUE;
8570 
8571  /* exchange the last variable in the clique if possible and add all new ones */
8572  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8573  {
8574  SCIP_VAR** clqvars;
8575  int lastfit = jstart + 1;
8576  assert(lastfit < i);
8577 
8578  /* copy all 'main'-clique variables */
8579  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8580  ++lastfit;
8581 
8582  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8583  while( lastfit <= i && j >= nposbinvars )
8584  {
8585  /* check if two variables are in a clique */
8586  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8587  {
8588  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8589  clqvars[lastfit - jstart - 2] = binvars[j];
8590 
8591  assert(i - lastfit + 2 >= 2);
8592  /* add clique with at least two variables */
8593  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8594 
8595  if( infeasible )
8596  {
8597  *cutoff = TRUE;
8598  break;
8599  }
8600 
8601  *nchgbds += nbdchgs;
8602 
8603  cliquenonzerosadded += (i - lastfit + 2);
8604  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8605  {
8606  stopped = TRUE;
8607  break;
8608  }
8609 
8610  --j;
8611  }
8612  else
8613  ++lastfit;
8614  }
8615 
8616  SCIPfreeBufferArray(scip, &clqvars);
8617  }
8618  }
8619  }
8620 
8621  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8622  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8623  {
8624  /* check for fixed variables */
8625  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8626 
8627  if( !*cutoff )
8628  {
8629  /* tighten variable's bounds */
8630  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8631 
8632  if( !*cutoff )
8633  {
8634  /* check for fixed variables */
8635  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8636 
8637  if( !*cutoff )
8638  {
8639  /* sort variables by variable type */
8640  SCIP_CALL( consdataSort(scip, consdata) );
8641 
8642  /* recompute activities if needed */
8643  if( !consdata->validactivities )
8644  consdataCalcActivities(scip, consdata);
8645  assert(consdata->validactivities);
8646 
8647  nvars = consdata->nvars;
8648  vars = consdata->vars;
8649  vals = consdata->vals;
8650  nposbinvars = 0;
8651  nnegbinvars = 0;
8652  allonebinary = 0;
8653 
8654  /* update binary variables */
8655  for( i = 0; i < nvars; ++i )
8656  {
8657  if( SCIPvarIsBinary(vars[i]) )
8658  {
8659  assert(!SCIPisZero(scip, vals[i]));
8660 
8661  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8662  ++allonebinary;
8663 
8664  binvars[nposbinvars + nnegbinvars] = vars[i];
8665  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8666 
8667  if( SCIPisPositive(scip, vals[i]) )
8668  ++nposbinvars;
8669  else
8670  ++nnegbinvars;
8671 
8672  assert(nposbinvars + nnegbinvars <= nvars);
8673  }
8674  /* stop searching for binary variables, because the constraint data is sorted */
8675  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8676  break;
8677  }
8678  assert(nposbinvars + nnegbinvars <= nvars);
8679  }
8680  }
8681  }
8682 
8683  oldnchgbds = *nchgbds;
8684  }
8685 
8686  /* case c) */
8687  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8688  {
8689  SCIP_Bool* values;
8690 
8691  /* initialize clique values array for adding a negated clique */
8692  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8693  BMSclearMemoryArray(values, nnegbinvars);
8694 
8695  /* compute value that needs to be exceeded */
8696  threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity);
8697 
8698  i = nposbinvars + nnegbinvars - 1;
8699  j = i - 1;
8700 
8701 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8702  /* check if the variable should not have already been fixed to one */
8703  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8704 #endif
8705 
8706  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8707  {
8708  --j;
8709  /* check for extending the clique */
8710  while( j >= nposbinvars )
8711  {
8712  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8713  break;
8714  --j;
8715  }
8716  jstart = j;
8717 
8718  assert(i - j >= 2);
8719  /* add negated clique with at least two variables */
8720  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8721 
8722  if( infeasible )
8723  *cutoff = TRUE;
8724 
8725  *nchgbds += nbdchgs;
8726 
8727  cliquenonzerosadded += (i - j);
8728  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8729  stopped = TRUE;
8730 
8731  /* exchange the last variable in the clique if possible and add all new ones */
8732  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8733  {
8734  SCIP_VAR** clqvars;
8735  int lastfit = j + 1;
8736  assert(lastfit < i);
8737 
8738  /* copy all 'main'-clique variables */
8739  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8740  ++lastfit;
8741 
8742  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8743  while( lastfit <= i && j >= nposbinvars )
8744  {
8745  /* check if two variables are in a negated clique */
8746  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8747  {
8748  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8749  clqvars[lastfit - jstart - 2] = binvars[j];
8750 
8751  assert(i - lastfit + 2 >= 2);
8752  /* add clique with at least two variables */
8753  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8754 
8755  if( infeasible )
8756  {
8757  *cutoff = TRUE;
8758  break;
8759  }
8760 
8761  *nchgbds += nbdchgs;
8762 
8763  cliquenonzerosadded += (i - lastfit + 2);
8764  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8765  {
8766  stopped = TRUE;
8767  break;
8768  }
8769 
8770  --j;
8771  }
8772  else
8773  ++lastfit;
8774  }
8775 
8776  SCIPfreeBufferArray(scip, &clqvars);
8777  }
8778  }
8779 
8780  SCIPfreeBufferArray(scip, &values);
8781  }
8782 
8783  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8784  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8785  {
8786  /* check for fixed variables */
8787  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8788 
8789  if( !*cutoff )
8790  {
8791  /* tighten variable's bounds */
8792  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8793 
8794  if( !*cutoff )
8795  {
8796  /* check for fixed variables */
8797  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8798 
8799  if( !*cutoff )
8800  {
8801  /* sort variables by variable type */
8802  SCIP_CALL( consdataSort(scip, consdata) );
8803 
8804  /* recompute activities if needed */
8805  if( !consdata->validactivities )
8806  consdataCalcActivities(scip, consdata);
8807  assert(consdata->validactivities);
8808 
8809  nvars = consdata->nvars;
8810  vars = consdata->vars;
8811  vals = consdata->vals;
8812  nposbinvars = 0;
8813  nnegbinvars = 0;
8814  allonebinary = 0;
8815 
8816  /* update binary variables */
8817  for( i = 0; i < nvars; ++i )
8818  {
8819  if( SCIPvarIsBinary(vars[i]) )
8820  {
8821  assert(!SCIPisZero(scip, vals[i]));
8822 
8823  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8824  ++allonebinary;
8825 
8826  binvars[nposbinvars + nnegbinvars] = vars[i];
8827  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8828 
8829  if( SCIPisPositive(scip, vals[i]) )
8830  ++nposbinvars;
8831  else
8832  ++nnegbinvars;
8833 
8834  assert(nposbinvars + nnegbinvars <= nvars);
8835  }
8836  /* stop searching for binary variables, because the constraint data is sorted */
8837  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8838  break;
8839  }
8840  assert(nposbinvars + nnegbinvars <= nvars);
8841  }
8842  }
8843  }
8844  }
8845 
8846  /* case d) */
8847  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8848  {
8849  SCIP_Bool* values;
8850 
8851  /* initialize clique values array for adding a negated clique */
8852  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8853  BMSclearMemoryArray(values, nposbinvars);
8854 
8855  /* compute value that needs to be exceeded */
8856  threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity);
8857 
8858  j = 1;
8859 
8860 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8861  /* check if the variable should not have already been fixed to one */
8862  assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8863 #endif
8864 
8865  if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8866  {
8867  ++j;
8868  /* check for extending the clique */
8869  while( j < nposbinvars )
8870  {
8871  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8872  break;
8873  ++j;
8874  }
8875  assert(j >= 2);
8876 
8877  /* add negated clique with at least two variables */
8878  SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8879 
8880  if( infeasible )
8881  *cutoff = TRUE;
8882 
8883  *nchgbds += nbdchgs;
8884 
8885  cliquenonzerosadded += j;
8886  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8887  stopped = TRUE;
8888 
8889  /* exchange the last variable in the clique if possible and add all new ones */
8890  if( !stopped && !(*cutoff) && j < nposbinvars )
8891  {
8892  SCIP_VAR** clqvars;
8893  int lastfit = j - 2;
8894  assert(lastfit >= 0);
8895 
8896  /* copy all 'main'-clique variables */
8897  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8898 
8899  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8900  while( lastfit >= 0 && j < nposbinvars )
8901  {
8902  /* check if two variables are in a negated clique */
8903  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8904  {
8905  clqvars[lastfit + 1] = binvars[j];
8906 
8907  /* add clique with at least two variables */
8908  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8909 
8910  if( infeasible )
8911  {
8912  *cutoff = TRUE;
8913  break;
8914  }
8915 
8916  *nchgbds += nbdchgs;
8917 
8918  cliquenonzerosadded += lastfit + 2;
8919  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8920  break;
8921 
8922  ++j;
8923  }
8924  else
8925  --lastfit;
8926  }
8927 
8928  SCIPfreeBufferArray(scip, &clqvars);
8929  }
8930  }
8931 
8932  SCIPfreeBufferArray(scip, &values);
8933  }
8934  }
8935 
8936  SCIPfreeBufferArray(scip, &binvarvals);
8937  SCIPfreeBufferArray(scip, &binvars);
8938 
8939  if( *cutoff )
8940  return SCIP_OKAY;
8941  }
8942 
8943  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8944 
8945  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8946  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8947  */
8948  nposcoefs = 0;
8949  nnegcoefs = 0;
8950  for( i = 0; i < nvars; ++i )
8951  {
8952  if( !SCIPvarIsBinary(vars[i]) )
8953  return SCIP_OKAY;
8954  else if( SCIPisEQ(scip, vals[i], +1.0) )
8955  nposcoefs++;
8956  else if( SCIPisEQ(scip, vals[i], -1.0) )
8957  nnegcoefs++;
8958  else
8959  return SCIP_OKAY;
8960  }
8961 
8962  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8963  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8964 
8965  if( lhsclique || rhsclique )
8966  {
8967  SCIP_Bool* values;
8968  int nbdchgs;
8969 
8970  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8971  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8972  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8973 
8974  for( i = 0; i < nvars; ++i )
8975  values[i] = (rhsclique == (vals[i] > 0.0));
8976 
8977  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8978 
8979  if( infeasible )
8980  *cutoff = TRUE;
8981 
8982  *nchgbds += nbdchgs;
8983  SCIPfreeBufferArray(scip, &values);
8984  }
8985 
8986  return SCIP_OKAY;
8987 }
8988 
8989 /** tightens left and right hand side of constraint due to integrality */
8990 static
8992  SCIP* scip, /**< SCIP data structure */
8993  SCIP_CONS* cons, /**< linear constraint */
8994  int* nchgsides, /**< pointer to count number of side changes */
8995  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
8996  )
8997 {
8998  SCIP_CONSDATA* consdata;
8999  SCIP_Real newlhs;
9000  SCIP_Real newrhs;
9001  SCIP_Bool chglhs;
9002  SCIP_Bool chgrhs;
9003  SCIP_Bool integral;
9004  int i;
9005 
9006  assert(scip != NULL);
9007  assert(cons != NULL);
9008  assert(nchgsides != NULL);
9009  assert(infeasible != NULL);
9011  consdata = SCIPconsGetData(cons);
9012  assert(consdata != NULL);
9013 
9014  *infeasible = FALSE;
9015 
9016  chglhs = FALSE;
9017  chgrhs = FALSE;
9018  newlhs = -SCIPinfinity(scip);
9019  newrhs = SCIPinfinity(scip);
9020 
9021  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
9022  {
9023  integral = TRUE;
9024  for( i = 0; i < consdata->nvars && integral; ++i )
9025  {
9026  integral = SCIPisIntegral(scip, consdata->vals[i])
9027  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
9028  }
9029  if( integral )
9030  {
9031  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
9032  {
9033  newlhs = SCIPfeasCeil(scip, consdata->lhs);
9034  chglhs = TRUE;
9035  }
9036  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
9037  {
9038  newrhs = SCIPfeasFloor(scip, consdata->rhs);
9039  chgrhs = TRUE;
9040  }
9041 
9042  /* check whether rounding would lead to an unsatisfiable constraint */
9043  if( SCIPisGT(scip, newlhs, newrhs) )
9044  {
9045  SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
9046  "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
9047 
9048  *infeasible = TRUE;
9049  return SCIP_OKAY;
9050  }
9051 
9052  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
9053  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9054 
9055  if( chglhs )
9056  {
9057  assert(!SCIPisInfinity(scip, -newlhs));
9058 
9059  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9060  if( !consdata->upgraded )
9061  (*nchgsides)++;
9062  }
9063  if( chgrhs )
9064  {
9065  assert(!SCIPisInfinity(scip, newrhs));
9066 
9067  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9068  if( !consdata->upgraded )
9069  (*nchgsides)++;
9070  }
9071  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9072  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9073  }
9074  }
9075 
9076  return SCIP_OKAY;
9077 }
9078 
9079 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9080  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
9081  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9082  * (i) ai >= 0:
9083  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
9084  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9085  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9086  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9087  * - change coefficients:
9088  * ai' := max(lhs - minact, maxact - rhs)
9089  * lhs' := lhs - (ai - ai')*li
9090  * rhs' := rhs - (ai - ai')*ui
9091  * (ii) ai < 0:
9092  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
9093  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9094  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9095  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9096  * - change coefficients:
9097  * ai' := min(rhs - maxact, minact - lhs)
9098  * lhs' := lhs - (ai - ai')*ui
9099  * rhs' := rhs - (ai - ai')*li
9100  *
9101  * We further try to remove redundant variable from the constraint;
9102  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9103  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9104  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9105  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9106  * 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
9107  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9108  *
9109  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9110  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9111  */
9112 static
9114  SCIP* scip, /**< SCIP data structure */
9115  SCIP_CONS* cons, /**< linear constraint */
9116  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
9117  int* nchgsides /**< pointer to count number of side changes */
9118  )
9119 {
9120  SCIP_CONSDATA* consdata;
9121  SCIP_VAR* var;
9122  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9123  * activity, ignoring the coefficients contributing with infinite value */
9124  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9125  * activity, ignoring the coefficients contributing with infinite value */
9126  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9127  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9128  SCIP_Bool isminsettoinfinity;
9129  SCIP_Bool ismaxsettoinfinity;
9130  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9131  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9132  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9133  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9134  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9135  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9136  SCIP_Real val;
9137  SCIP_Real newval;
9138  SCIP_Real newlhs;
9139  SCIP_Real newrhs;
9140  SCIP_Real lb;
9141  SCIP_Real ub;
9142  int i;
9143 
9144  assert(scip != NULL);
9145  assert(cons != NULL);
9146  assert(nchgcoefs != NULL);
9147  assert(nchgsides != NULL);
9148 
9149  consdata = SCIPconsGetData(cons);
9150  assert(consdata != NULL);
9151 
9152  /* @todo Is this still needed with automatic recomputation of activities? */
9153  /* if the maximal coefficient is too large, recompute the activities */
9154  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9155  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9156  {
9157  consdataRecomputeMinactivity(scip, consdata);
9158  consdataRecomputeMaxactivity(scip, consdata);
9159  }
9160 
9161  /* get the minimal and maximal activity of the constraint */
9162  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9163  &isminsettoinfinity, &ismaxsettoinfinity);
9164 
9165  minleftactivity = 0.0;
9166  maxleftactivity = 0.0;
9167 
9168  /* try to tighten each coefficient */
9169  i = 0;
9170  while( i < consdata->nvars )
9171  {
9172  var = consdata->vars[i];
9173 
9174  /* get coefficient and variable's bounds */
9175  lb = SCIPvarGetLbLocal(var);
9176  ub = SCIPvarGetUbLocal(var);
9177  val = consdata->vals[i];
9178  assert(!SCIPisZero(scip, val));
9179 
9180  /* check sign of coefficient */
9181  if( val >= 0.0 )
9182  {
9183  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9185  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9186  {
9187  /* change coefficients:
9188  * ai' := max(lhs - minact, maxact - rhs)
9189  * lhs' := lhs - (ai - ai')*li
9190  * rhs' := rhs - (ai - ai')*ui
9191  */
9192 
9193  lval = consdata->lhs - minactivity;
9194  rval = maxactivity - consdata->rhs;
9195 
9196  /* Try to avoid cancellation, if there are only two variables */
9197  if( consdata->nvars == 2 )
9198  {
9199  SCIP_Real otherval;
9200  otherval = consdata->vals[1-i];
9201 
9202  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9203  {
9204  lval = consdata->lhs - val*lb;
9205  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9206  }
9207 
9208  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9209  {
9210  rval = val*ub - consdata->rhs;
9211  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9212  }
9213  }
9214 
9215  newval = MAX(lval, rval);
9216  assert(SCIPisSumRelLE(scip, newval, val));
9217 
9218  /* Try to avoid cancellation in computation of lhs/rhs */
9219  newlhs = consdata->lhs - val * lb;
9220  newlhs += newval * lb;
9221  newrhs = consdata->rhs - val * ub;
9222  newrhs += newval * ub;
9223 
9224  if( !SCIPisSumRelEQ(scip, newval, val) )
9225  {
9226  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9227  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9228  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9229 
9230  /* update the coefficient and the activity bounds */
9231  if( SCIPisZero(scip, newval) )
9232  {
9233  SCIP_CALL( delCoefPos(scip, cons, i) );
9234  i--;
9235  }
9236  else
9237  {
9238  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9239  }
9240  (*nchgcoefs)++;
9241 
9242  /* get the new minimal and maximal activity of the constraint */
9243  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9244  &isminsettoinfinity, &ismaxsettoinfinity);
9245 
9246  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9247  {
9248  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9249 
9250  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9251  (*nchgsides)++;
9252  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9253  }
9254 
9255  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9256  {
9257  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9258 
9259  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9260  (*nchgsides)++;
9261  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9262  }
9263  }
9264  }
9265  else
9266  {
9267  if( !SCIPisInfinity(scip, -minleftactivity) )
9268  {
9269  assert(!SCIPisInfinity(scip, val));
9270  assert(!SCIPisInfinity(scip, lb));
9271  if( SCIPisInfinity(scip, -lb) )
9272  minleftactivity = -SCIPinfinity(scip);
9273  else
9274  minleftactivity += val * lb;
9275  }
9276 
9277  if( !SCIPisInfinity(scip, maxleftactivity) )
9278  {
9279  assert(!SCIPisInfinity(scip, val));
9280  assert(!SCIPisInfinity(scip, -ub));
9281  if( SCIPisInfinity(scip,ub) )
9282  maxleftactivity = SCIPinfinity(scip);
9283  else
9284  maxleftactivity += val * ub;
9285  }
9286  }
9287  }
9288  else
9289  {
9290  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9292  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9293  {
9294  /* change coefficients:
9295  * ai' := min(rhs - maxact, minact - lhs)
9296  * lhs' := lhs - (ai - ai')*ui
9297  * rhs' := rhs - (ai - ai')*li
9298  */
9299 
9300  lval = minactivity - consdata->lhs;
9301  rval = consdata->rhs - maxactivity;
9302 
9303  /* Try to avoid cancellation, if there are only two variables */
9304  if( consdata->nvars == 2 )
9305  {
9306  SCIP_Real otherval;
9307  otherval = consdata->vals[1-i];
9308 
9309  if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9310  {
9311  lval = val*ub - consdata->lhs;
9312  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9313  }
9314 
9315  if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9316  {
9317  rval = consdata->rhs - val*lb;
9318  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9319  }
9320  }
9321 
9322  newval = MIN(lval, rval);
9323  assert(SCIPisSumRelGE(scip, newval, val));
9324 
9325  /* Try to avoid cancellation in computation of lhs/rhs */
9326  newlhs = consdata->lhs - val * ub;
9327  newlhs += newval * ub;
9328  newrhs = consdata->rhs - val * lb;
9329  newrhs += newval * lb;
9330 
9331  if( !SCIPisSumRelEQ(scip, newval, val) )
9332  {
9333  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9334  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9335  minactivity, maxactivity, consdata->lhs, consdata->rhs);
9336 
9337  /* update the coefficient and the activity bounds */
9338  if( SCIPisZero(scip, newval) )
9339  {
9340  SCIP_CALL( delCoefPos(scip, cons, i) );
9341  i--;
9342  }
9343  else
9344  {
9345  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9346  }
9347  (*nchgcoefs)++;
9348 
9349  /* get the new minimal and maximal activity of the constraint */
9350  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9351  &isminsettoinfinity, &ismaxsettoinfinity);
9352 
9353  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9354  {
9355  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9356 
9357  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9358  (*nchgsides)++;
9359  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9360  }
9361 
9362  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9363  {
9364  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9365 
9366  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9367  (*nchgsides)++;
9368  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9369  }
9370  }
9371  }
9372  else
9373  {
9374  if( !SCIPisInfinity(scip, -minleftactivity) )
9375  {
9376  assert(!SCIPisInfinity(scip, -val));
9377  assert(!SCIPisInfinity(scip, -ub));
9378  if( SCIPisInfinity(scip, ub) )
9379  minleftactivity = -SCIPinfinity(scip);
9380  else
9381  minleftactivity += val * ub;
9382  }
9383 
9384  if( !SCIPisInfinity(scip, maxleftactivity) )
9385  {
9386  assert(!SCIPisInfinity(scip, -val));
9387  assert(!SCIPisInfinity(scip, lb));
9388  if( SCIPisInfinity(scip, -lb) )
9389  maxleftactivity = SCIPinfinity(scip);
9390  else
9391  maxleftactivity += val * lb;
9392  }
9393  }
9394  }
9395  ++i;
9396  }
9397 
9398  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9399  minleftactivity, consdata->rhs);
9400  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9401  maxleftactivity, consdata->lhs);
9402 
9403  /* minleft == \infty ==> minactivity == \infty */
9404  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9405  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9406 
9407  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9408  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9409  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9410  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9411  */
9412  assert(!SCIPisInfinity(scip, minactivity));
9413  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9414  return SCIP_OKAY;
9415 
9416  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9417  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9418  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9419  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9420  */
9421  assert(!SCIPisInfinity(scip, -maxactivity));
9422  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9423  return SCIP_OKAY;
9424 
9425  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9426  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9427  */
9428  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9429  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9430 
9431  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9432  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9433  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9434  * they can be removed from the constraint.
9435  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9436  */
9437  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9438  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9439  {
9440  SCIP_Real minleftactivitypart;
9441  SCIP_Real maxleftactivitypart;
9442 
9443  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9444 
9445  /* try to remove redundant variables from constraint */
9446  i = 0;
9447  while( i < consdata->nvars )
9448  {
9449  var = consdata->vars[i];
9450  minleftactivitypart = 0.0;
9451  maxleftactivitypart = 0.0;
9452  lb = SCIPvarGetLbLocal(var);
9453  ub = SCIPvarGetUbLocal(var);
9454 
9455  /* get coefficient and variable's bounds */
9456  val = consdata->vals[i];
9457  assert(!SCIPisZero(scip, val));
9458 
9459  /* check sign of coefficient */
9460  if( val >= 0.0 )
9461  {
9462  /* negation of condition above in case of positive val */
9464  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9465  {
9466  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9467  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9468  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9469  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9470 
9471  minleftactivitypart = val * lb;
9472  maxleftactivitypart = val * ub;
9473 
9474  SCIP_CALL( delCoefPos(scip, cons, i) );
9475  i--;
9476 
9477  /* get the new minimal and maximal activity of the constraint */
9478  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9479  &isminsettoinfinity, &ismaxsettoinfinity);
9480 
9481  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9482  * huge contributions
9483  */
9484  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9485  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9486  }
9487  }
9488  else
9489  {
9490  /* negation of condition above in case of negative val */
9492  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9493  {
9494  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9495  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9496 
9497  minleftactivitypart = val * ub;
9498  maxleftactivitypart = val * lb;
9499 
9500  SCIP_CALL( delCoefPos(scip, cons, i) );
9501  i--;
9502 
9503  /* get the new minimal and maximal activity of the constraint */
9504  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9505  &isminsettoinfinity, &ismaxsettoinfinity);
9506 
9507  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9508  * huge contributions
9509  */
9510  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9511  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9512  }
9513  }
9514 
9515  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9516  * redundant variables could get deleted,
9517  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9518  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9519  * we would also delete y2 and as a result we would have gotten infeasibility */
9520  /* adjust lhs and right hand side */
9521  newlhs = consdata->lhs - minleftactivitypart;
9522  newrhs = consdata->rhs - maxleftactivitypart;
9523 
9524  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9525  {
9526  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9527  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9528  ++(*nchgsides);
9529  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9530  }
9531  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9532  {
9533  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9534  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9535  ++(*nchgsides);
9536  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9537  }
9538  ++i;
9539  }
9540  }
9541 
9542  return SCIP_OKAY;
9543 }
9544 
9545 /** processes equality with only one variable by fixing the variable and deleting the constraint */
9546 static
9548  SCIP* scip, /**< SCIP data structure */
9549  SCIP_CONS* cons, /**< linear constraint */
9550  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9551  int* nfixedvars, /**< pointer to count number of fixed variables */
9552  int* ndelconss /**< pointer to count number of deleted constraints */
9553  )
9554 {
9555  SCIP_CONSDATA* consdata;
9556  SCIP_VAR* var;
9557  SCIP_Real val;
9558  SCIP_Real fixval;
9559  SCIP_Bool infeasible;
9560  SCIP_Bool fixed;
9561 
9562  assert(scip != NULL);
9563  assert(cons != NULL);
9564  assert(cutoff != NULL);
9565  assert(nfixedvars != NULL);
9566  assert(ndelconss != NULL);
9567 
9568  consdata = SCIPconsGetData(cons);
9569  assert(consdata != NULL);
9570  assert(consdata->nvars == 1);
9571  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9572 
9573  /* calculate the value to fix the variable to */
9574  var = consdata->vars[0];
9575  val = consdata->vals[0];
9576  assert(!SCIPisZero(scip, val));
9577  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9578  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9579  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9580  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9581 
9582  /* fix variable */
9583  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9584  if( infeasible )
9585  {
9586  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9587  *cutoff = TRUE;
9588  return SCIP_OKAY;
9589  }
9590  if( fixed )
9591  (*nfixedvars)++;
9592 
9593  /* disable constraint */
9594  SCIP_CALL( SCIPdelCons(scip, cons) );
9595  if( !consdata->upgraded )
9596  (*ndelconss)++;
9597 
9598  return SCIP_OKAY;
9599 }
9600 
9601 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9602 static
9604  SCIP* scip, /**< SCIP data structure */
9605  SCIP_CONS* cons, /**< linear constraint */
9606  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9607  int* naggrvars, /**< pointer to count number of aggregated variables */
9608  int* ndelconss /**< pointer to count number of deleted constraints */
9609  )
9610 {
9611  SCIP_CONSDATA* consdata;
9612  SCIP_Bool infeasible;
9613  SCIP_Bool redundant;
9614  SCIP_Bool aggregated;
9615 
9616  assert(scip != NULL);
9617  assert(cons != NULL);
9618  assert(cutoff != NULL);
9619  assert(naggrvars != NULL);
9620  assert(ndelconss != NULL);
9621 
9622  consdata = SCIPconsGetData(cons);
9623  assert(consdata != NULL);
9624  assert(consdata->nvars == 2);
9625  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9626 
9627  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9628  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9629  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9630 
9631  /* aggregate the equality */
9632  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9633  consdata->rhs, &infeasible, &redundant, &aggregated) );
9634 
9635  /* check for infeasibility of aggregation */
9636  if( infeasible )
9637  {
9638  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9639  *cutoff = TRUE;
9640  return SCIP_OKAY;
9641  }
9642 
9643  /* count the aggregation */
9644  if( aggregated )
9645  (*naggrvars)++;
9646 
9647  /* delete the constraint, if it is redundant */
9648  if( redundant )
9649  {
9650  SCIP_CALL( SCIPdelCons(scip, cons) );
9651 
9652  if( !consdata->upgraded )
9653  (*ndelconss)++;
9654  }
9655 
9656  return SCIP_OKAY;
9657 }
9658 
9659 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9660 static
9662  SCIP* scip, /**< SCIP data structure */
9663  SCIP_CONSDATA* consdata, /**< linear constraint data */
9664  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9665  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9666  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9667  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9668  )
9669 {
9670  SCIP_Real slackvarlb;
9671  SCIP_Real slackvarub;
9672 
9673  assert(scip != NULL);
9674  assert(consdata != NULL);
9675  assert(newlhs != NULL);
9676  assert(newrhs != NULL);
9677  assert(!SCIPisInfinity(scip, -consdata->lhs));
9678  assert(!SCIPisInfinity(scip, consdata->rhs));
9679 
9680  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9681  slackvarub = SCIPvarGetUbGlobal(slackvar);
9682  if( slackcoef > 0.0 )
9683  {
9684  if( SCIPisInfinity(scip, -slackvarlb) )
9685  *newrhs = SCIPinfinity(scip);
9686  else
9687  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9688  if( SCIPisInfinity(scip, slackvarub) )
9689  *newlhs = -SCIPinfinity(scip);
9690  else
9691  *newlhs = consdata->lhs - slackcoef * slackvarub;
9692  }
9693  else
9694  {
9695  if( SCIPisInfinity(scip, -slackvarlb) )
9696  *newlhs = -SCIPinfinity(scip);
9697  else
9698  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9699  if( SCIPisInfinity(scip, slackvarub) )
9700  *newrhs = SCIPinfinity(scip);
9701  else
9702  *newrhs = consdata->lhs - slackcoef * slackvarub;
9703  }
9704  assert(SCIPisLE(scip, *newlhs, *newrhs));
9705 }
9706 
9707 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9708  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9709  * is implicitly integral by this constraint
9710  *
9711  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9712  * can help.
9713  */
9714 static
9716  SCIP* scip, /**< SCIP data structure */
9717  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9718  SCIP_CONS* cons, /**< linear constraint */
9719  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9720  int* naggrvars, /**< pointer to count number of aggregated variables */
9721  int* ndelconss /**< pointer to count number of deleted constraints */
9722  )
9723 {
9724  SCIP_CONSDATA* consdata;
9725  SCIP_VAR** vars;
9726  SCIP_Real* vals;
9727  SCIP_VARTYPE bestslacktype;
9728  SCIP_VARTYPE slacktype;
9729  SCIP_Real lhs;
9730  SCIP_Real rhs;
9731  SCIP_Real bestslackdomrng;
9732  SCIP_Real minabsval;
9733  SCIP_Real maxabsval;
9734  SCIP_Bool bestremovescons;
9735  SCIP_Bool coefszeroone;
9736  SCIP_Bool coefsintegral;
9737  SCIP_Bool varsintegral;
9738  SCIP_Bool infeasible;
9739  SCIP_Bool samevar;
9740  int supinf; /* counter for infinite contributions to the supremum of a possible
9741  * multi-aggregation
9742  */
9743  int infinf; /* counter for infinite contributions to the infimum of a possible
9744  * multi-aggregation
9745  */
9746  int maxnlocksstay;
9747  int maxnlocksremove;
9748  int bestslackpos;
9749  int bestnlocks;
9750  int ncontvars;
9751  int contvarpos;
9752  int nintvars;
9753  int nimplvars;
9754  int intvarpos;
9755  int v;
9756 
9757  assert(scip != NULL);
9758  assert(cons != NULL);
9759  assert(cutoff != NULL);
9760  assert(naggrvars != NULL);
9761 
9762  consdata = SCIPconsGetData(cons);
9763  assert(consdata != NULL);
9764  assert(consdata->nvars > 2);
9765  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9766 
9767  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9768 
9769  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9770  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9771  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9772  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9773  */
9774  lhs = consdata->lhs;
9775  rhs = consdata->rhs;
9776  maxnlocksstay = 0;
9777  if( consdata->nvars == 3 )
9778  {
9779  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9780  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9781  */
9782  maxnlocksremove = 3;
9783  }
9784  else if( consdata->nvars == 4 )
9785  {
9786  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9787  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9788  */
9789  maxnlocksremove = 2;
9790  }
9791  else
9792  {
9793  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9794  maxnlocksremove = 1;
9795  }
9796 
9797  /* the locks on this constraint can be ignored */
9798  if( SCIPconsIsChecked(cons) )
9799  {
9800  if( !SCIPisInfinity(scip, -lhs) )
9801  {
9802  maxnlocksstay++;
9803  maxnlocksremove++;
9804  }
9805  if( !SCIPisInfinity(scip, rhs) )
9806  {
9807  maxnlocksstay++;
9808  maxnlocksremove++;
9809  }
9810  }
9811 
9812  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9813  vars = consdata->vars;
9814  vals = consdata->vals;
9815  bestslackpos = -1;
9816  bestslacktype = SCIP_VARTYPE_BINARY;
9817  bestnlocks = INT_MAX;
9818  bestremovescons = FALSE;
9819  bestslackdomrng = 0.0;
9820  coefszeroone = TRUE;
9821  coefsintegral = TRUE;
9822  varsintegral = TRUE;
9823  ncontvars = 0;
9824  contvarpos = -1;
9825  nintvars = 0;
9826  nimplvars = 0;
9827  intvarpos = -1;
9828  minabsval = SCIPinfinity(scip);
9829  maxabsval = -1.0;
9830  for( v = 0; v < consdata->nvars; ++v )
9831  {
9832  SCIP_VAR* var;
9833  SCIP_Real val;
9834  SCIP_Real absval;
9835  SCIP_Real varlb;
9836  SCIP_Real varub;
9837  SCIP_Bool iscont;
9838  int nlocks;
9839 
9840  assert(vars != NULL);
9841  assert(vals != NULL);
9842 
9843  var = vars[v];
9844  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9845  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9846  varlb = SCIPvarGetLbGlobal(var);
9847  varub = SCIPvarGetUbGlobal(var);
9848 
9849  val = vals[v];
9850  absval = REALABS(val);
9851  assert(SCIPisPositive(scip, absval));
9852 
9853  /* calculate minimal and maximal absolute value */
9854  if( absval < minabsval )
9855  minabsval = absval;
9856  if( absval > maxabsval )
9857  maxabsval = absval;
9858 
9859  /* do not try to multi aggregate, when numerical bad */
9860  if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9861  return SCIP_OKAY;
9862 
9863  slacktype = SCIPvarGetType(var);
9864  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9865  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9866  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9867  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9868 
9869  /* update candidates for continuous -> implint and integer -> implint conversion */
9870  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9871  {
9872  ncontvars++;
9873  contvarpos = v;
9874  }
9875  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9876  {
9877  ++nimplvars;
9878  }
9879  else if( slacktype == SCIP_VARTYPE_INTEGER )
9880  {
9881  nintvars++;
9882  intvarpos = v;
9883  }
9884 
9885  /* check, if variable is already fixed or aggregated */
9886  if( !SCIPvarIsActive(var) )
9887  continue;
9888 
9889  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9891 
9892  if( nlocks > maxnlocksremove )
9893  continue;
9894 
9895  /* check, if variable can be used as a slack variable */
9896  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9897  !SCIPdoNotMultaggrVar(scip, var) )
9898  {
9899  SCIP_Bool better;
9900  SCIP_Bool equal;
9901  SCIP_Real slackdomrng;
9902 
9903  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9904  slackdomrng = SCIPinfinity(scip);
9905  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9906  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9907  return SCIP_OKAY;
9908  else
9909  {
9910  slackdomrng = (varub - varlb)*absval;
9911  assert(!SCIPisInfinity(scip, slackdomrng));
9912  }
9913  equal = FALSE;
9914  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9915  if( !better && slacktype == bestslacktype )
9916  {
9917  better = (nlocks < bestnlocks);
9918  if( nlocks == bestnlocks && !bestremovescons )
9919  {
9920  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9921  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9922  }
9923  }
9924 
9925  if( better || equal )
9926  {
9927  SCIP_Real minresactivity;
9928  SCIP_Real maxresactivity;
9929  SCIP_Real newlhs;
9930  SCIP_Real newrhs;
9931  SCIP_Bool removescons;
9932  SCIP_Bool minisrelax;
9933  SCIP_Bool maxisrelax;
9934  SCIP_Bool isminsettoinfinity;
9935  SCIP_Bool ismaxsettoinfinity;
9936 
9937  /* check if the constraint becomes redundant after multi-aggregation */
9938  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9939  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9940 
9941  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9942  * activity
9943  */
9944  if( minisrelax || maxisrelax )
9945  continue;
9946 
9947  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9948  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9949 
9950  /* check resactivities for reliability */
9951  if( removescons )
9952  {
9953  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9954  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9955 
9956  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9957  && SCIPisFeasLE(scip, newlhs, minresactivity))
9958  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9959 
9960  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9961  }
9962 
9963  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9964  if( conshdlrdata->multaggrremove && !removescons )
9965  continue;
9966 
9967  /* prefer variables that make the constraints redundant */
9968  if( bestremovescons && !removescons )
9969  continue;
9970 
9971  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9972  * other constraints
9973  */
9974  if( !removescons && nlocks > maxnlocksstay )
9975  continue;
9976 
9977  better = better || (!bestremovescons && removescons);
9978  if( better )
9979  {
9980  bestslackpos = v;
9981  bestslacktype = slacktype;
9982  bestnlocks = nlocks;
9983  bestslackdomrng = slackdomrng;
9984  bestremovescons = removescons;
9985  }
9986  }
9987  }
9988  }
9989 
9990  /* if all coefficients and variables are integral, the right hand side must also be integral */
9991  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9992  {
9993  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9994  SCIPdebugPrintCons(scip, cons, NULL);
9995  *cutoff = TRUE;
9996  return SCIP_OKAY;
9997  }
9998 
9999  supinf = 0;
10000  infinf = 0;
10001  samevar = FALSE;
10002 
10003  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
10004  for( v = 0; v < consdata->nvars; ++v )
10005  {
10006  if( v != bestslackpos )
10007  {
10008  if( SCIPisPositive(scip, consdata->vals[v]) )
10009  {
10010  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10011  {
10012  ++supinf;
10013  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10014  {
10015  ++infinf;
10016  samevar = TRUE;
10017  }
10018  }
10019  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10020  ++infinf;
10021  }
10022  else if( SCIPisNegative(scip, consdata->vals[v]) )
10023  {
10024  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
10025  {
10026  ++supinf;
10027  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10028  {
10029  ++infinf;
10030  samevar = TRUE;
10031  }
10032  }
10033  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
10034  ++infinf;
10035  }
10036  }
10037  }
10038  assert(!samevar || (supinf > 0 && infinf > 0));
10039 
10040  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10041  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10042  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
10043  {
10044  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10045  return SCIP_OKAY;
10046  }
10047 
10048  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
10049  * we cannot aggregate the variable, because the integrality condition would get lost
10050  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
10051  * loose the integrality condition for this variable.
10052  */
10053  if( bestslackpos >= 0
10054  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
10055  || (coefsintegral && varsintegral && nimplvars == 0)) )
10056  {
10057  SCIP_VAR* slackvar;
10058  SCIP_Real* scalars;
10059  SCIP_Real slackcoef;
10060  SCIP_Real aggrconst;
10061  SCIP_Real newlhs;
10062  SCIP_Real newrhs;
10063  SCIP_Bool aggregated;
10064 
10065  /* we found a slack variable that only occurs in at most one other constraint:
10066  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10067  */
10068  assert(bestslackpos < consdata->nvars);
10069 
10070  /* do not multi aggregate binary variables */
10071  if( SCIPvarIsBinary(vars[bestslackpos]) )
10072  return SCIP_OKAY;
10073 
10074  /* convert equality into inequality by deleting the slack variable:
10075  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
10076  */
10077  slackvar = vars[bestslackpos];
10078  slackcoef = vals[bestslackpos];
10079  assert(!SCIPisZero(scip, slackcoef));
10080  aggrconst = consdata->rhs/slackcoef;
10081 
10082  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10083  assert(SCIPisLE(scip, newlhs, newrhs));
10084  SCIP_CALL( chgLhs(scip, cons, newlhs) );
10085  SCIP_CALL( chgRhs(scip, cons, newrhs) );
10086  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10087 
10088  /* allocate temporary memory */
10089  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10090 
10091  /* set up the multi-aggregation */
10092  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10093  for( v = 0; v < consdata->nvars; ++v )
10094  {
10095  scalars[v] = -consdata->vals[v]/slackcoef;
10096  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10097  }
10098  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10099  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10100  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10101 
10102  /* perform the multi-aggregation */
10103  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10104  &infeasible, &aggregated) );
10105  assert(aggregated);
10106 
10107  /* free temporary memory */
10108  SCIPfreeBufferArray(scip, &scalars);
10109 
10110  /* check for infeasible aggregation */
10111  if( infeasible )
10112  {
10113  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10114  *cutoff = TRUE;
10115  return SCIP_OKAY;
10116  }
10117 
10118  (*naggrvars)++;
10119 
10120  /* delete the constraint if it became redundant */
10121  if( bestremovescons )
10122  {
10123  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10124  SCIP_CALL( SCIPdelCons(scip, cons) );
10125 
10126  if( !consdata->upgraded )
10127  (*ndelconss)++;
10128  }
10129  }
10130  else if( ncontvars == 1 )
10131  {
10132  SCIP_VAR* var;
10133 
10134  assert(0 <= contvarpos && contvarpos < consdata->nvars);
10135  var = vars[contvarpos];
10136  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
10137 
10138  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10139  {
10140  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10141  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10142  {
10143  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10144  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10145  SCIPconsGetName(cons), SCIPvarGetName(var));
10146  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10147  if( infeasible )
10148  {
10149  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10150  *cutoff = TRUE;
10151 
10152  return SCIP_OKAY;
10153  }
10154  }
10155  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10156  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10157  else if( !SCIPdoNotAggr(scip) )
10158  {
10159  SCIP_VAR* newvar;
10160  SCIP_Real absval;
10161  char newvarname[SCIP_MAXSTRLEN];
10162  SCIP_Bool redundant;
10163  SCIP_Bool aggregated;
10164 
10165  absval = REALABS(vals[contvarpos]);
10166 
10167  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10168 
10169  /* create new implicit variable for aggregation */
10170  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10172 
10173  /* add new variable to problem */
10174  SCIP_CALL( SCIPaddVar(scip, newvar) );
10175 
10176 #ifdef WITH_DEBUG_SOLUTION
10177  if( SCIPdebugIsMainscip(scip) )
10178  {
10179  SCIP_Real varval;
10180  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10181  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10182  }
10183 #endif
10184 
10185  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10186  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10187  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10188 
10189  /* aggregate continuous and implicit variable */
10190  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10191 
10192  if( infeasible )
10193  {
10194  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10195  SCIPvarGetName(var), SCIPvarGetName(newvar));
10196  *cutoff = TRUE;
10197 
10198  /* release implicit variable */
10199  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10200 
10201  return SCIP_OKAY;
10202  }
10203 
10204  /* release implicit variable */
10205  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10206 
10207  if( aggregated )
10208  (*naggrvars)++;
10209  else
10210  return SCIP_OKAY;
10211  }
10212 
10213  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10214  * again
10215  */
10216  consdata->boundstightened = 0;
10217  consdata->rangedrowpropagated = 0;
10218  consdata->presolved = FALSE;
10219  }
10220  }
10221  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10222  {
10223  SCIP_VAR* var;
10224 
10225  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10226  * -> we don't convert integers into implints if the row is a 0/1-row
10227  */
10228  assert(varsintegral);
10229  assert(0 <= intvarpos && intvarpos < consdata->nvars);
10230  var = vars[intvarpos];
10231  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10232 
10233  if( coefsintegral
10234  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10235  && SCIPisFeasIntegral(scip, consdata->rhs) )
10236  {
10237  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10238  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10239  SCIPconsGetName(cons), SCIPvarGetName(var));
10240  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10241  if( infeasible )
10242  {
10243  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10244  *cutoff = TRUE;
10245 
10246  return SCIP_OKAY;
10247  }
10248  }
10249  }
10250 
10251  return SCIP_OKAY;
10252 }
10253 
10254 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10255 static
10257  SCIP* scip, /**< SCIP data structure */
10258  SCIP_CONSDATA* consdata, /**< linear constraint data */
10259  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
10260  * objective function */
10261  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
10262  * this constraint */
10263  )
10264 {
10265  SCIP_VAR** vars;
10266  SCIP_VAR* var;
10267  SCIP_Real objval;
10268  SCIP_Bool negated;
10269  int nvars;
10270  int v;
10271 
10272  vars = consdata->vars;
10273  nvars = consdata->nvars;
10274 
10275  assert(vars != NULL);
10276 
10277  for( v = 0; v < nvars; ++v )
10278  {
10279  negated = FALSE;
10280  var = vars[v];
10281  assert(var != NULL);
10282 
10283  if( SCIPvarIsNegated(var) )
10284  {
10285  negated = TRUE;
10286  var = SCIPvarGetNegatedVar(var);
10287  assert(var != NULL);
10288  }
10289 
10290  objval = SCIPvarGetObj(var);
10291 
10292  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10293  * function
10294  */
10295  if( SCIPisZero(scip, objval) )
10296  return FALSE;
10297  else
10298  {
10299  SCIP_Real val;
10300 
10301  val = consdata->vals[v];
10302 
10303  if( negated )
10304  {
10305  if( v == 0 )
10306  {
10307  /* the first variable defines the scale */
10308  (*scale) = val / -objval;
10309 
10310  (*offset) += val;
10311  }
10312  else if( SCIPisEQ(scip, -objval * (*scale), val) )
10313  (*offset) += val;
10314  else
10315  return FALSE;
10316  }
10317  else if( v == 0 )
10318  {
10319  /* the first variable defines the scale */
10320  (*scale) = val / objval;
10321  }
10322  else if( !SCIPisEQ(scip, objval * (*scale), val) )
10323  return FALSE;
10324  }
10325  }
10326 
10327  return TRUE;
10328 }
10329 
10330 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10331  * objective coefficients and add an objective offset
10332  */
10333 static
10335  SCIP* scip, /**< SCIP data structure */
10336  SCIP_CONS* cons, /**< linear equation constraint */
10337  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10338  )
10339 {
10340  SCIP_CONSDATA* consdata;
10341  SCIP_Real offset;
10342  SCIP_Real scale;
10343  SCIP_Bool applicable;
10344  int nobjvars;
10345  int nvars;
10346  int v;
10347 
10348  assert(scip != NULL);
10349  assert(cons != NULL);
10350  assert(conshdlrdata != NULL);
10351 
10352  consdata = SCIPconsGetData(cons);
10353  assert(consdata != NULL);
10354  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10355 
10356  nvars = consdata->nvars;
10357  nobjvars = SCIPgetNObjVars(scip);
10358 
10359  /* check if the linear equality constraints does not have more variables than the objective function */
10360  if( nvars > nobjvars || nvars == 0 )
10361  return SCIP_OKAY;
10362 
10363  /* check for allowance of algorithm */
10364  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10365  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10366  return SCIP_OKAY;
10367 
10368  offset = consdata->rhs;
10369  scale = 1.0;
10370 
10371  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10372  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10373 
10374  if( applicable )
10375  {
10376  SCIP_VAR** vars;
10377 
10378  vars = consdata->vars;
10379  assert(vars != NULL);
10380 
10381  offset /= scale;
10382 
10383  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10384  SCIPconsGetName(cons), consdata->rhs, offset);
10385 
10386  /* make equality a model constraint to ensure optimality in this direction */
10387  SCIP_CALL( SCIPsetConsChecked(scip, cons, TRUE) );
10388  SCIP_CALL( SCIPsetConsEnforced(scip, cons, TRUE) );
10389 
10390  /* set all objective coefficient to zero */
10391  for( v = 0; v < nvars; ++v )
10392  {
10393  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10394  }
10395 
10396  /* add an objective offset */
10397  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10398  }
10399 
10400  return SCIP_OKAY;
10401 }
10402 
10403 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10404 static
10406  SCIP* scip, /**< SCIP data structure */
10407  SCIP_CONS* cons, /**< constraint */
10408  SCIP_Real primalbound /**< feasible primal bound */
10409  )
10410 {
10411  SCIP_Real cutoffbound;
10412 
10413  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10414  * accepted
10415  */
10416  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10417 
10418  if( cutoffbound < SCIPgetCutoffbound(scip) )
10419  {
10420  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10421 
10422  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10423  }
10424  else
10425  {
10426  SCIP_CONSDATA* consdata;
10427 
10428  consdata = SCIPconsGetData(cons);
10429  assert(consdata != NULL);
10430 
10431  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10432  * resulted from one side
10433  */
10434  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10435  {
10436  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10437  * propagation
10438  */
10439  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10440  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10441  }
10442  }
10443 
10444  return SCIP_OKAY;
10445 }
10446 
10447 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10448  * constraint enters the LP by setting the initial and separated flag to FALSE
10449  */
10450 static
10452  SCIP* scip, /**< SCIP data structure */
10453  SCIP_CONS* cons, /**< linear constraint */
10454  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10455  )
10456 {
10457  SCIP_CONSDATA* consdata;
10458  SCIP_Real offset;
10459  SCIP_Real scale;
10460  SCIP_Bool applicable;
10461  int nobjvars;
10462  int nvars;
10463 
10464  assert(scip != NULL);
10465  assert(cons != NULL);
10466  assert(conshdlrdata != NULL);
10467 
10468  consdata = SCIPconsGetData(cons);
10469  assert(consdata != NULL);
10471  /* ignore equalities since these are covered by the method checkPartialObjective() */
10472  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10473  return SCIP_OKAY;
10474 
10475  nvars = consdata->nvars;
10476  nobjvars = SCIPgetNObjVars(scip);
10477 
10478  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10479  * initial and/or separated flag is set to FALSE
10480  */
10481  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10482  return SCIP_OKAY;
10483 
10484  offset = 0.0;
10485  scale = 1.0;
10486 
10487  /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves
10488  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10489  */
10490  if( nobjvars == 0 )
10491  return SCIP_OKAY;
10492 
10493  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10494  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10495 
10496  if( applicable )
10497  {
10498  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10499  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10500 
10501  assert(scale != 0.0);
10502 
10503  if( scale > 0.0 )
10504  {
10505  if( conshdlrdata->detectcutoffbound && rhsfinite )
10506  {
10507  SCIP_Real primalbound;
10508 
10509  primalbound = (consdata->rhs - offset) / scale;
10510 
10511  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10512  SCIPconsGetName(cons), primalbound);
10513 
10514  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10515  }
10516 
10517  if( conshdlrdata->detectlowerbound && lhsfinite )
10518  {
10519  SCIP_Real lowerbound;
10520 
10521  lowerbound = (consdata->lhs - offset) / scale;
10522 
10523  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10524  SCIPconsGetName(cons), lowerbound);
10525 
10526  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10527  }
10528 
10529  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10530  (conshdlrdata->detectlowerbound && !rhsfinite) )
10531  {
10532  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10533  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10534  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10535  }
10536  }
10537  else
10538  {
10539  if( conshdlrdata->detectlowerbound && rhsfinite )
10540  {
10541  SCIP_Real lowerbound;
10542 
10543  lowerbound = (consdata->rhs - offset) / scale;
10544 
10545  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10546  SCIPconsGetName(cons), lowerbound);
10547 
10548  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10549  }
10550 
10551  if( conshdlrdata->detectcutoffbound && lhsfinite )
10552  {
10553  SCIP_Real primalbound;
10554 
10555  primalbound = (consdata->lhs - offset) / scale;
10556 
10557  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10558  SCIPconsGetName(cons), primalbound);
10559 
10560  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10561  }
10562 
10563  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10564  (conshdlrdata->detectlowerbound && !lhsfinite) )
10565  {
10566  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10567  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10568  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10569  }
10570  }
10571  }
10572 
10573  return SCIP_OKAY;
10574 }
10575 
10576 /** converts special equalities */
10577 static
10579  SCIP* scip, /**< SCIP data structure */
10580  SCIP_CONS* cons, /**< linear constraint */
10581  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10582  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10583  int* nfixedvars, /**< pointer to count number of fixed variables */
10584  int* naggrvars, /**< pointer to count number of aggregated variables */
10585  int* ndelconss /**< pointer to count number of deleted constraints */
10586  )
10587 {
10588  SCIP_CONSDATA* consdata;
10589 
10590  assert(scip != NULL);
10591  assert(cons != NULL);
10592  assert(conshdlrdata != NULL);
10593  assert(cutoff != NULL);
10594  assert(nfixedvars != NULL);
10595  assert(naggrvars != NULL);
10596  assert(ndelconss != NULL);
10598  consdata = SCIPconsGetData(cons);
10599  assert(consdata != NULL);
10600  assert(consdata->removedfixings);
10601 
10602  /* do nothing on inequalities */
10603  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10604  return SCIP_OKAY;
10605 
10606  /* depending on the number of variables, call a special conversion method */
10607  if( consdata->nvars == 1 )
10608  {
10609  /* fix variable */
10610  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10611  }
10612  else if( consdata->nvars == 2 )
10613  {
10614  /* aggregate one of the variables */
10615  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10616  }
10617  else
10618  {
10619  /* check if the equality is part of the objective function */
10620  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10621 
10622  /* try to multi-aggregate one of the variables */
10623  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10624  }
10625 
10626  return SCIP_OKAY;
10627 }
10628 
10629 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10630  * integral
10631  */
10632 static
10634  SCIP* scip, /**< SCIP data structure */
10635  SCIP_CONSDATA* consdata, /**< linear constraint */
10636  int pos, /**< position of variable to be left out */
10637  SCIP_Real val /**< value to divide the coefficients by */
10638  )
10639 {
10640  int v;
10641 
10642  assert(scip != NULL);
10643  assert(consdata != NULL);
10644  assert(0 <= pos && pos < consdata->nvars);
10645 
10646  for( v = 0; v < consdata->nvars; ++v )
10647  {
10648  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10649  return FALSE;
10650  }
10651 
10652  return TRUE;
10653 }
10654 
10655 /** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$,
10656  * check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$
10657  */
10658 static
10660  SCIP* scip, /**< SCIP data structure */
10661  SCIP_Real side, /**< lhs or rhs */
10662  SCIP_Real val, /**< coefficient */
10663  SCIP_Real minresactivity, /**< minimal residual activity */
10664  SCIP_Real maxresactivity, /**< maximal residual activity */
10665  SCIP_Real* minval, /**< pointer to store calculated minval */
10666  SCIP_Real* maxval /**< pointer to store calculated maxval */
10667  )
10668 {
10669  assert(scip != NULL);
10670  assert(minval != NULL);
10671  assert(maxval != NULL);
10672 
10673  if( val > 0.0 )
10674  {
10675  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10676  *minval = -maxresactivity;
10677  else
10678  *minval = (side - maxresactivity)/val;
10679 
10680  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10681  *maxval = -minresactivity;
10682  else
10683  *maxval = (side - minresactivity)/val;
10684  }
10685  else
10686  {
10687  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10688  *minval = minresactivity;
10689  else
10690  *minval = (side - minresactivity)/val;
10691 
10692  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10693  *maxval = maxresactivity;
10694  else
10695  *maxval = (side - maxresactivity)/val;
10696  }
10697 }
10698 
10699 
10700 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10701  * linear inequality
10702  */
10703 static
10705  SCIP* scip, /**< SCIP data structure */
10706  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10707  SCIP_CONS* cons, /**< linear constraint */
10708  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10709  int* nfixedvars, /**< pointer to count number of fixed variables */
10710  int* naggrvars, /**< pointer to count number of aggregated variables */
10711  int* ndelconss /**< pointer to count number of deleted constraints */
10712  )
10713 {
10714  SCIP_CONSDATA* consdata;
10715  SCIP_Bool lhsexists;
10716  SCIP_Bool rhsexists;
10717  SCIP_Bool bestisint;
10718  SCIP_Bool bestislhs;
10719  SCIP_Real minabsval;
10720  SCIP_Real maxabsval;
10721  int bestpos;
10722  int i;
10723  int maxotherlocks;
10724 
10725  assert(scip != NULL);
10726  assert(cons != NULL);
10727  assert(cutoff != NULL);
10728  assert(nfixedvars != NULL);
10729  assert(naggrvars != NULL);
10730  assert(ndelconss != NULL);
10731 
10732  /* only process checked constraints (for which the locks are increased);
10733  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10734  * dualfix presolver
10735  */
10736  if( !SCIPconsIsChecked(cons) )
10737  return SCIP_OKAY;
10738 
10739  consdata = SCIPconsGetData(cons);
10740  assert(consdata != NULL);
10741 
10742  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10743  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10744 
10745  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10746  * can use it safely for aggregation and break the search loop
10747  */
10748  bestpos = -1;
10749  bestisint = TRUE;
10750  bestislhs = FALSE;
10751 
10752  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10753  * everything else would produce fill-in. Exceptions:
10754  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10755  * produced.
10756  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10757  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10758  * six nonzeros (two variables per substitution).
10759  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10760  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10761  * six nonzeros (three variables per substitution). God exists!
10762  */
10763  if( consdata->nvars <= 2 )
10764  maxotherlocks = INT_MAX;
10765  else if( consdata->nvars == 3 )
10766  maxotherlocks = 3;
10767  else if( consdata->nvars == 4 )
10768  maxotherlocks = 2;
10769  else
10770  maxotherlocks = 1;
10771 
10772  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10773  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10774  maxotherlocks++;
10775 
10776  minabsval = SCIPinfinity(scip);
10777  maxabsval = -1.0;
10778  for( i = 0; i < consdata->nvars && bestisint; ++i )
10779  {
10780  SCIP_VAR* var;
10781  SCIP_Bool isint;
10782  SCIP_Real val;
10783  SCIP_Real absval;
10784  SCIP_Real obj;
10785  SCIP_Real lb;
10786  SCIP_Real ub;
10787  SCIP_Bool agglhs;
10788  SCIP_Bool aggrhs;
10789 
10790  val = consdata->vals[i];
10791  absval = REALABS(val);
10792 
10793  /* calculate minimal and maximal absolute value */
10794  if( absval < minabsval )
10795  minabsval = absval;
10796  if( absval > maxabsval )
10797  maxabsval = absval;
10798 
10799  /* do not try to multi aggregate, when numerical bad */
10800  if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10801  return SCIP_OKAY;
10802 
10803  var = consdata->vars[i];
10805 
10806  /* if we already found a candidate, skip integers */
10807  if( bestpos >= 0 && isint )
10808  continue;
10809 
10810  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10811  * active, fixed, or single-aggregated with another binary variable
10812  */
10813  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10814  continue;
10815 
10816  if ( SCIPdoNotMultaggrVar(scip, var) )
10817  continue;
10818 
10819  val = consdata->vals[i];
10820  obj = SCIPvarGetObj(var);
10821  lb = SCIPvarGetLbGlobal(var);
10822  ub = SCIPvarGetUbGlobal(var);
10823 
10824  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10825  *
10826  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10827  * - constraint is the only one that forbids fixing the variable to its lower bound
10828  * - 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
10829  *
10830  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10831  * - constraint is the only one that forbids fixing the variable to its upper bound
10832  * - 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
10833  *
10834  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10835  * - constraint is the only one that forbids fixing the variable to its upper bound
10836  * - 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
10837  *
10838  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10839  * - constraint is the only one that forbids fixing the variable to its lower bound
10840  * - 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
10841  *
10842  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10843  * of all x_j
10844  * furthermore: we only want to apply this, if no fill-in will be produced
10845  */
10846  agglhs = lhsexists
10847  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10848  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10849  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10850  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10851  aggrhs = rhsexists
10852  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10853  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10854  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10855  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10856  if( agglhs || aggrhs )
10857  {
10858  SCIP_Real minresactivity;
10859  SCIP_Real maxresactivity;
10860  SCIP_Real minval;
10861  SCIP_Real maxval;
10862  SCIP_Bool minisrelax;
10863  SCIP_Bool maxisrelax;
10864  SCIP_Bool isminsettoinfinity;
10865  SCIP_Bool ismaxsettoinfinity;
10866 
10867  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10868  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10869  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10870  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10871 
10872  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10873  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10874  * This is needed, because we do not want to rely on relaxed finite resactivities.
10875  */
10876  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10877 
10878  if( agglhs )
10879  {
10880  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10881  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10882 
10883  assert(SCIPisLE(scip, minval, maxval));
10884  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10885  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10886  {
10887  SCIP_Real oldmaxresactivity;
10888  SCIP_Real oldminresactivity;
10889  SCIP_Bool recalculated;
10890 
10891  recalculated = FALSE;
10892  oldmaxresactivity = maxresactivity;
10893  oldminresactivity = minresactivity;
10894 
10895  /* check minresactivity for reliability */
10896  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10897  {
10898  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10899  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10900  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10901  }
10902 
10903  /* check maxresactivity for reliability */
10904  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10905  {
10906  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10907  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10908  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10909  }
10910 
10911  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10912  if( recalculated )
10913  {
10914  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10915 
10916  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10917  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10918 
10919  assert(SCIPisLE(scip, minval, maxval));
10920  }
10921 
10922  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10923  {
10924  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10925  * in the multi-aggregation
10926  */
10927  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10928  {
10929  bestpos = i;
10930  bestisint = isint;
10931  bestislhs = TRUE;
10932  continue; /* no need to also look at the right hand side */
10933  }
10934  }
10935  }
10936  }
10937 
10938  if( aggrhs )
10939  {
10940  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10941  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10942 
10943  assert(SCIPisLE(scip,minval,maxval));
10944  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10945  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10946  {
10947  SCIP_Real oldmaxresactivity;
10948  SCIP_Real oldminresactivity;
10949  SCIP_Bool recalculated;
10950 
10951  recalculated = FALSE;
10952  oldmaxresactivity = maxresactivity;
10953  oldminresactivity = minresactivity;
10954 
10955  /* check minresactivity for reliability */
10956  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10957  {
10958  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10959  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10960  }
10961 
10962  /* check maxresactivity for reliability */
10963  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10964  {
10965  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10966  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10967  }
10968 
10969  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10970  if( recalculated )
10971  {
10972  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10973  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10974  assert(SCIPisLE(scip,minval,maxval));
10975  }
10976 
10977  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10978  {
10979  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10980  * in the multi-aggregation
10981  */
10982  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10983  {
10984  bestpos = i;
10985  bestisint = isint;
10986  bestislhs = FALSE;
10987  }
10988  }
10989  }
10990  }
10991  }
10992  }
10993 
10994  if( bestpos >= 0 )
10995  {
10996  SCIP_VAR** aggrvars;
10997  SCIP_Real* aggrcoefs;
10998  SCIP_Real aggrconst;
10999  SCIP_VAR* bestvar;
11000  SCIP_Real bestval;
11001  SCIP_Real epsilon;
11002  int naggrs;
11003  int j;
11004  SCIP_Bool infeasible;
11005  SCIP_Bool aggregated;
11006  SCIP_Bool samevar;
11007  int supinf; /* counter for infinite contributions to the supremum of a possible
11008  * multi-aggregation
11009  */
11010  int infinf; /* counter for infinite contributions to the infimum of a possible
11011  * multi-aggregation
11012  */
11013 
11014  assert(!bestislhs || lhsexists);
11015  assert(bestislhs || rhsexists);
11016 
11017  bestvar = consdata->vars[bestpos];
11018  bestval = consdata->vals[bestpos];
11019  assert(bestisint ==
11021 
11022  /* allocate temporary memory */
11023  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
11024  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
11025 
11026  /* set up the multi-aggregation */
11027  SCIPdebugPrintCons(scip, cons, NULL);
11028  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
11029  naggrs = 0;
11030  supinf = 0;
11031  infinf = 0;
11032  samevar = FALSE;
11033  epsilon = SCIPepsilon(scip);
11034 
11035  for( j = 0; j < consdata->nvars; ++j )
11036  {
11037  if( j != bestpos )
11038  {
11039  SCIP_Real absaggrcoef;
11040 
11041  aggrvars[naggrs] = consdata->vars[j];
11042  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
11043  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
11044 
11045  absaggrcoef = REALABS(aggrcoefs[naggrs]);
11046 
11047  /* do not try to multi aggregate, when numerical bad */
11048  if( absaggrcoef < epsilon )
11049  {
11050  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
11051 
11052  /* free temporary memory */
11053  SCIPfreeBufferArray(scip, &aggrcoefs);
11054  SCIPfreeBufferArray(scip, &aggrvars);
11055 
11056  return SCIP_OKAY;
11057  }
11058 
11059  if( bestisint )
11060  {
11061  /* coefficient must be integral: round it to exact integral value */
11062  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
11063  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
11064  }
11065 
11066  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
11067  {
11068  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11069  {
11070  ++supinf;
11071  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11072  {
11073  ++infinf;
11074  samevar = TRUE;
11075  }
11076  }
11077  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11078  ++infinf;
11079  }
11080  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11081  {
11082  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11083  {
11084  ++supinf;
11085  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11086  {
11087  ++infinf;
11088  samevar = TRUE;
11089  }
11090  }
11091  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11092  ++infinf;
11093  }
11094 
11095  naggrs++;
11096  }
11097  }
11098  assert(!samevar || (supinf > 0 && infinf > 0));
11099 
11100  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11101  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11102  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11103  assert(naggrs == consdata->nvars-1);
11104 
11105  /* right hand side must be integral: round it to exact integral value */
11106  if( bestisint )
11107  {
11108  assert(SCIPisIntegral(scip, aggrconst));
11109  aggrconst = SCIPfloor(scip, aggrconst+0.5);
11110  }
11111 
11112  aggregated = FALSE;
11113  infeasible = FALSE;
11114 
11115  /* perform the multi-aggregation */
11116  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11117  {
11118  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11119  * also convertLongEquality() early termination due to coefficients
11120  */
11121  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11122 
11123  /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because
11124  * the implicitness might rely on the constraint and the integrality of bestvar
11125  */
11126  if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER )
11127  {
11128  SCIP_Bool infeasiblevartypechg;
11129 
11130  for( j = 0; j < naggrs; ++j)
11131  {
11132  /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not
11133  * lead to infeasibility
11134  */
11135  if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT )
11136  {
11137  SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) );
11138  assert(!infeasiblevartypechg);
11139  }
11140  }
11141  }
11142  }
11143  else
11144  {
11145  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11146  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11147  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11148  }
11149  /* free temporary memory */
11150  SCIPfreeBufferArray(scip, &aggrcoefs);
11151  SCIPfreeBufferArray(scip, &aggrvars);
11152 
11153  /* check for infeasible aggregation */
11154  if( infeasible )
11155  {
11156  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11157  *cutoff = TRUE;
11158  return SCIP_OKAY;
11159  }
11160 
11161  /* delete the constraint, if the aggregation was successful */
11162  if( aggregated )
11163  {
11164  SCIP_CALL( SCIPdelCons(scip, cons) );
11165 
11166  if( !consdata->upgraded )
11167  (*ndelconss)++;
11168  (*naggrvars)++;
11169  }
11170  else
11171  {
11172  SCIPdebugMsg(scip, "aggregation non successful!\n");
11173  }
11174  }
11175 
11176  return SCIP_OKAY;
11177 }
11178 
11179 #define BINWEIGHT 1
11180 #define INTWEIGHT 4
11181 #define CONTWEIGHT 8
11182 
11183 /** gets weight for variable in a "weighted number of variables" sum */
11184 static
11185 int getVarWeight(
11186  SCIP_VAR* var /**< variable to get weight for */
11187  )
11188 {
11189  switch( SCIPvarGetType(var) )
11190  {
11191  case SCIP_VARTYPE_BINARY:
11192  return BINWEIGHT;
11193  case SCIP_VARTYPE_INTEGER:
11194  case SCIP_VARTYPE_IMPLINT:
11195  return INTWEIGHT;
11197  return CONTWEIGHT;
11198  default:
11199  SCIPerrorMessage("invalid variable type\n");
11201  return 0; /*lint !e527*/
11202  }
11203 }
11205 /** tries to aggregate variables in equations a^Tx = lhs
11206  * in case there are at most two binary variables with an odd coefficient and all other
11207  * variables are not continuous and have an even coefficient then:
11208  * - exactly one odd binary variables
11209  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11210  * - lhs is odd -> y = 1
11211  * - lhs is even -> y = 0
11212  * - exactly two odd binary variables
11213  * aggregate the two binary variables with odd coefficient
11214  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11215  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11216  */
11217 static
11219  SCIP* scip, /**< SCIP data structure */
11220  SCIP_CONS* cons, /**< linear constraint */
11221  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11222  int* nfixedvars, /**< pointer to count number of fixed variables */
11223  int* naggrvars /**< pointer to count number of aggregated variables */
11224  )
11225 { /*lint --e{715}*/
11226  SCIP_CONSDATA* consdata;
11227  SCIP_Bool success;
11228 
11229  assert( scip != NULL );
11230  assert( cons != NULL );
11231 
11232  consdata = SCIPconsGetData(cons);
11233  assert( consdata != NULL );
11234 
11235  /* check if the linear constraint is an equation with integral right hand side */
11236  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11237  return SCIP_OKAY;
11238 
11239  /* try to fix and aggregated variables until nothing is possible anymore */
11240  do
11241  {
11242  int v;
11243  int nvars;
11244  SCIP_VAR** vars;
11245  SCIP_Real* vals;
11246  SCIP_Real lhs;
11247  SCIP_Bool lhsodd;
11248 
11249  SCIP_Bool infeasible;
11250  SCIP_Bool fixed;
11251  SCIP_Bool aggregated;
11252  SCIP_Bool redundant;
11253 
11254  SCIP_VAR* var1;
11255  SCIP_VAR* var2;
11256  int noddvars;
11257 
11258  success = FALSE;
11259 
11260  lhs = consdata->lhs;
11261  vars = consdata->vars;
11262  vals = consdata->vals;
11263  nvars = consdata->nvars;
11264 
11265  assert( !SCIPisInfinity(scip, ABS(lhs)) );
11266 
11267  var1 = NULL;
11268  var2 = NULL;
11269  noddvars = 0;
11270 
11271  /* search for binary variables with an odd coefficient */
11272  for( v = 0; v < nvars && noddvars < 3; ++v )
11273  {
11274  SCIP_Longint val;
11275 
11276  /* all coefficients and variables have to be integral */
11277  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11278  return SCIP_OKAY;
11279 
11280  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11281  if( val % 2 != 0 )
11282  {
11283  /* the odd values have to belong to binary variables */
11284  if( !SCIPvarIsBinary(vars[v]) )
11285  return SCIP_OKAY;
11286 
11287  if( noddvars == 0 )
11288  var1 = vars[v];
11289  else
11290  var2 = vars[v];
11291 
11292  noddvars++;
11293  }
11294  }
11295 
11296  /* check lhs is odd or even */
11297  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11298 
11299  if( noddvars == 1 )
11300  {
11301  assert( var1 != NULL );
11302 
11303  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11304  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11305 
11306  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11307 
11308  /* check for infeasibility of fixing */
11309  if( infeasible )
11310  {
11311  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11312  *cutoff = TRUE;
11313  return SCIP_OKAY;
11314  }
11315 
11316  if( fixed )
11317  {
11318  SCIPdebugMsg(scip, " -> feasible fixing\n");
11319  (*nfixedvars)++;
11320  success = TRUE;
11321  }
11322  }
11323  else if( noddvars == 2 )
11324  {
11325  assert( var1 != NULL );
11326  assert( var2 != NULL );
11327 
11328  /* aggregate the two variables with odd coefficient
11329  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11330  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11331  */
11332  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11333  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11334 
11335  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11336  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11337 
11338  /* check for infeasibility of aggregation */
11339  if( infeasible )
11340  {
11341  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11342  *cutoff = TRUE;
11343  return SCIP_OKAY;
11344  }
11345 
11346  /* count the aggregation */
11347  if( aggregated )
11348  {
11349  SCIPdebugMsg(scip, " -> feasible aggregation\n");
11350  (*naggrvars)++;
11351  success = TRUE;
11352  }
11353  }
11354 
11355  if( success )
11356  {
11357  /* apply fixings and aggregation to successfully rerun this presolving step */
11358  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11359 
11360  if( infeasible )
11361  {
11362  SCIPdebugMsg(scip, " -> infeasible fixing\n");
11363  *cutoff = TRUE;
11364  return SCIP_OKAY;
11365  }
11366 
11367  /* normalize constraint */
11368  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11369 
11370  if( infeasible )
11371  {
11372  SCIPdebugMsg(scip, " -> infeasible normalization\n");
11373  *cutoff = TRUE;
11374  return SCIP_OKAY;
11375  }
11376  }
11377  }
11378  while( success );
11379 
11380  return SCIP_OKAY;
11381 }
11382 
11383 
11384 
11385 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11386  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11387  * coefficients
11388  */
11389 static
11390 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11391 { /*lint --e{715}*/
11392  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11393  SCIP_VARTYPE vartype1;
11394  SCIP_VARTYPE vartype2;
11395  SCIP_Real value;
11396 
11397  assert(consdata != NULL);
11398  assert(0 <= ind1 && ind1 < consdata->nvars);
11399  assert(0 <= ind2 && ind2 < consdata->nvars);
11400 
11401  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11402  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11403 
11404  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11405  {
11406  /* continuous varibles will be sorted to the back */
11407  if( vartype2 != vartype1 )
11408  return +1;
11409  /* both variables are continuous */
11410  else
11411  return 0;
11412  }
11413  /* continuous variables will be sorted to the back */
11414  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11415  return -1;
11416 
11417  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11418 
11419  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11420  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11421 }
11422 
11423 /** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs
11424  *
11425  * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs,
11426  * then we can change this constraint to 1^Tx = 1
11427  */
11428 static
11430  SCIP* scip, /**< SCIP data structure */
11431  SCIP_CONS* cons, /**< linear constraint */
11432  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11433  int* nchgsides /**< pointer to store the amount of changed sides */
11434  )
11435 {
11436  SCIP_CONSDATA* consdata;
11437  SCIP_VAR** vars;
11438  SCIP_Real* vals;
11439  SCIP_Real minval;
11440  SCIP_Real secondminval;
11441  SCIP_Real maxval;
11442  SCIP_Real lhs;
11443  SCIP_Real rhs;
11444  int nvars;
11445  int v;
11446 
11447  /* we must not change a modifiable constraint in any way */
11449  return SCIP_OKAY;
11450 
11451  if( SCIPconsIsDeleted(cons) )
11452  return SCIP_OKAY;
11453 
11454  consdata = SCIPconsGetData(cons);
11455  assert(consdata != NULL);
11456 
11457  nvars = consdata->nvars;
11458 
11459  /* do not check empty or bound-constraints */
11460  if( nvars < 2 )
11461  return SCIP_OKAY;
11462 
11463  lhs = consdata->lhs;
11464  rhs = consdata->rhs;
11465  assert(!SCIPisInfinity(scip, -lhs));
11466  assert(!SCIPisInfinity(scip, rhs));
11467  assert(!SCIPisNegative(scip, rhs));
11468 
11469  /* sides must be positive and different to detect set partition */
11470  if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) )
11471  return SCIP_OKAY;
11472 
11473  vals = consdata->vals;
11474  vars = consdata->vars;
11475  assert(vars != NULL);
11476  assert(vals != NULL);
11477 
11478  minval = SCIP_INVALID;
11479  secondminval = SCIP_INVALID;
11480  maxval = -SCIP_INVALID;
11481 
11482  for( v = nvars - 1; v >= 0; --v )
11483  {
11484  if( SCIPvarIsBinary(vars[v]) )
11485  {
11486  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11487  {
11488  secondminval = minval;
11489  minval = vals[v];
11490  }
11491  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11492  secondminval = vals[v];
11493 
11494  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11495  maxval = vals[v];
11496  }
11497  else
11498  break;
11499  }
11500 
11501  /* check if all variables are binary, we can choose one, and need to choose at most one */
11502  if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs)
11503  && SCIPisGT(scip, minval + secondminval, rhs) )
11504  {
11505  /* change all coefficients to 1.0 */
11506  for( v = nvars - 1; v >= 0; --v )
11507  {
11508  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11509  }
11510  (*nchgcoefs) += nvars;
11511 
11512  /* replace old right and left hand side with 1.0 */
11513  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11514  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11515  (*nchgsides) += 2;
11516  }
11517 
11518  return SCIP_OKAY;
11519 }
11520 
11521 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11522  *
11523  * for both-sided constraints only @see rangedRowSimplify() will be called
11524  *
11525  * for one-sided constraints there are several different coefficient reduction steps which will be applied
11526  *
11527  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11528  *
11529  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11530  *
11531  * 2. We try to remove redundant fractional parts in a constraint
11532  *
11533  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11534  *
11535  * 3. We are using the greatest common divisor for further reductions
11536  *
11537  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11538  * integral
11539  */
11540 static
11542  SCIP* scip, /**< SCIP data structure */
11543  SCIP_CONS* cons, /**< linear constraint */
11544  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11545  int* nchgsides, /**< pointer to store the amount of changed sides */
11546  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11547  )
11548 {
11549  SCIP_CONSDATA* consdata;
11550  SCIP_VAR** vars;
11551  SCIP_Real* vals;
11552  int* perm;
11553  SCIP_Real minactsub;
11554  SCIP_Real maxactsub;
11555  SCIP_Real siderest;
11556  SCIP_Real feastol;
11557  SCIP_Real newcoef;
11558  SCIP_Real absval;
11559  SCIP_Real minact;
11560  SCIP_Real maxact;
11561  SCIP_Real side;
11562  SCIP_Real lhs;
11563  SCIP_Real rhs;
11564  SCIP_Real lb;
11565  SCIP_Real ub;
11566  SCIP_Longint restcoef;
11567  SCIP_Longint oldgcd;
11568  SCIP_Longint rest;
11569  SCIP_Longint gcd;
11570  SCIP_Bool isminsettoinfinity;
11571  SCIP_Bool ismaxsettoinfinity;
11572  SCIP_Bool isminrelax;
11573  SCIP_Bool ismaxrelax;
11574  SCIP_Bool allcoefintegral;
11575  SCIP_Bool onlybin;
11576  SCIP_Bool hasrhs;
11577  SCIP_Bool haslhs;
11578  int oldnchgcoefs;
11579  int oldnchgsides;
11580  int foundbin;
11581  int candpos;
11582  int candpos2;
11583  int offsetv;
11584  int nvars;
11585  int v;
11586  int w;
11587 
11588  assert(scip != NULL);
11589  assert(cons != NULL);
11590  assert(nchgcoefs != NULL);
11591  assert(nchgsides != NULL);
11592 
11593  *infeasible = FALSE;
11594 
11595  /* we must not change a modifiable constraint in any way */
11596  if( SCIPconsIsModifiable(cons) )
11597  return SCIP_OKAY;
11598 
11599  if( SCIPconsIsDeleted(cons) )
11600  return SCIP_OKAY;
11601 
11602  consdata = SCIPconsGetData(cons);
11603  assert(consdata != NULL);
11604 
11605  nvars = consdata->nvars;
11606 
11607  /* do not check empty or bound-constraints */
11608  if( nvars <= 2 )
11609  return SCIP_OKAY;
11610 
11611  /* update maximal activity delta if necessary */
11612  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11613  consdataRecomputeMaxActivityDelta(scip, consdata);
11614 
11615  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11616  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11617  checkMaxActivityDelta(scip, consdata);
11618 
11619  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11620  * accordingly
11621  */
11622  /* can only work with valid non-infinity activities per variable */
11623  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11624  return SCIP_OKAY;
11625 
11626  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11627  * but the eventsystem seems to be full
11628  */
11629  consdata->normalized = FALSE;
11630 
11631  /* normalize constraint */
11632  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11633  assert(nvars == consdata->nvars);
11634 
11635  if( *infeasible )
11636  return SCIP_OKAY;
11637 
11638  if( !consdata->normalized )
11639  return SCIP_OKAY;
11640 
11641  lhs = consdata->lhs;
11642  rhs = consdata->rhs;
11643  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11644  assert(!SCIPisNegative(scip, rhs));
11645 
11646  if( !SCIPisInfinity(scip, -lhs) )
11647  haslhs = TRUE;
11648  else
11649  haslhs = FALSE;
11650 
11651  if( !SCIPisInfinity(scip, rhs) )
11652  hasrhs = TRUE;
11653  else
11654  hasrhs = FALSE;
11655 
11656  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11657  SCIPdebug( oldnchgsides = *nchgsides; )
11658 
11659  /* @todo extend both-sided simplification */
11660  if( haslhs && hasrhs )
11661  {
11662  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11663 
11664  return SCIP_OKAY;
11665  }
11666  assert(haslhs != hasrhs);
11667 
11668  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11669  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11670  assert(!haslhs || !SCIPisNegative(scip, lhs));
11671 
11672  /* get temporary memory to store the sorted permutation */
11673  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11674 
11675  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11676  * value of their coefficients
11677  */
11678  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11679 
11680  /* perform sorting after permutation array */
11681  permSortConsdata(consdata, perm, nvars);
11682  consdata->indexsorted = FALSE;
11683  consdata->coefsorted = FALSE;
11684 
11685  vars = consdata->vars;
11686  vals = consdata->vals;
11687  assert(vars != NULL);
11688  assert(vals != NULL);
11689  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11690 
11691  /* free temporary memory */
11692  SCIPfreeBufferArray(scip, &perm);
11693 
11694  /* only check constraints with at least two non continuous variables */
11695  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11696  return SCIP_OKAY;
11697 
11698  /* do not process constraints when all coefficients are 1.0 */
11699  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11700  return SCIP_OKAY;
11701 
11702  feastol = SCIPfeastol(scip);
11703 
11704  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11705  SCIPdebugPrintCons(scip, cons, NULL);
11706 
11707  /* get global activities */
11708  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11709  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11710 
11711  /* cannot work with infinite activities */
11712  if( isminsettoinfinity || ismaxsettoinfinity )
11713  return SCIP_OKAY;
11714 
11715  assert(!isminrelax);
11716  assert(!ismaxrelax);
11717  assert(maxact > minact);
11718  assert(!SCIPisInfinity(scip, -minact));
11719  assert(!SCIPisInfinity(scip, maxact));
11720 
11721  v = 0;
11722  offsetv = -1;
11723  side = haslhs ? lhs : rhs;
11724  minactsub = minact;
11725  maxactsub = maxact;
11726 
11727  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11728  * do not need to look at the large coefficients
11729  *
11730  * e.g. all x are binary, z are positive integer
11731  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11732  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11733  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11734  *
11735  * can be changed to
11736  *
11737  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11738  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11739  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11740  */
11741 
11742  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11743  * hand side, we cannot apply the extra reduction step and need to reset v
11744  *
11745  * 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
11746  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11747  * for all i is a solution
11748  *
11749  * also redundancy of variables would not be correctly determined in such a case
11750  */
11751  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11752  {
11753  v = 1;
11754 
11755  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11756  {
11757  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11758  * extra step, which might have worked
11759  */
11760  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11761  {
11762  v = 0;
11763  break;
11764  }
11765 
11766  ++v;
11767  }
11768 
11769  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11770  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11771  if( v == nvars )
11772  return SCIP_OKAY;
11773 
11774  /* cannot work with continuous variables which have a big coefficient */
11775  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11776  return SCIP_OKAY;
11777 
11778  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11779  if( SCIPisEQ(scip, side, -vals[v]) )
11780  v = 0;
11781 
11782  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11783  * reduction
11784  */
11785  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11786  v = 0;
11787 
11788  if( v > 0 )
11789  {
11790  assert(v < nvars);
11791 
11792  offsetv = v - 1;
11793 
11794  for( w = 0; w < v; ++w )
11795  {
11796  lb = SCIPvarGetLbGlobal(vars[w]);
11797  ub = SCIPvarGetUbGlobal(vars[w]);
11798 
11799  assert(vals[w] > 0);
11800 
11801  /* update residual activities */
11802  maxactsub -= ub * vals[w];
11803  minactsub -= lb * vals[w];
11804  assert(maxactsub > minactsub);
11805  }
11806  }
11807  }
11808 
11809  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11810  *
11811  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11812  *
11813  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11814  * to
11815  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11816  */
11817  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11818  {
11819  SCIP_Bool redundant = FALSE;
11820  SCIP_Bool numericsok;
11821  SCIP_Bool rredundant;
11822  SCIP_Bool lredundant;
11823 
11824  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11825  assert(gcd >= 1);
11826 
11827  if( v == 0 )
11828  {
11829  lb = SCIPvarGetLbGlobal(vars[0]);
11830  ub = SCIPvarGetUbGlobal(vars[0]);
11831 
11832  /* update residual activities */
11833  if( vals[0] > 0 )
11834  {
11835  maxactsub -= ub * vals[0];
11836  minactsub -= lb * vals[0];
11837  }
11838  else
11839  {
11840  maxactsub -= lb * vals[0];
11841  minactsub -= ub * vals[0];
11842  }
11843  assert(maxactsub > minactsub);
11844  ++v;
11845  }
11846 
11847  siderest = -SCIP_INVALID;
11848  allcoefintegral = TRUE;
11849 
11850  /* check if some variables always fit into the given constraint */
11851  for( ; v < nvars - 1; ++v )
11852  {
11853  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11854  break;
11855 
11856  if( !SCIPisIntegral(scip, vals[v]) )
11857  {
11858  allcoefintegral = FALSE;
11859  break;
11860  }
11861 
11862  /* calculate greatest common divisor for all general and binary variables */
11863  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11864 
11865  if( gcd == 1 )
11866  break;
11867 
11868  lb = SCIPvarGetLbGlobal(vars[v]);
11869  ub = SCIPvarGetUbGlobal(vars[v]);
11870 
11871  assert(!SCIPisInfinity(scip, -lb));
11872  assert(!SCIPisInfinity(scip, ub));
11873 
11874  /* update residual activities */
11875  if( vals[v] > 0 )
11876  {
11877  maxactsub -= ub * vals[v];
11878  minactsub -= lb * vals[v];
11879  }
11880  else
11881  {
11882  maxactsub -= lb * vals[v];
11883  minactsub -= ub * vals[v];
11884  }
11885  assert(SCIPisGE(scip, maxactsub, minactsub));
11886 
11887  if( hasrhs )
11888  {
11889  /* determine the remainder of the right hand side and the gcd */
11890  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11891  }
11892  else
11893  {
11894  /* determine the remainder of the left hand side and the gcd */
11895  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11896  if( SCIPisZero(scip, siderest) )
11897  siderest = gcd;
11898  }
11899 
11900  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11901  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11902 
11903  /* early termination if the activities deceed the gcd */
11904  if( offsetv == -1 && (rredundant || lredundant) )
11905  {
11906  redundant = TRUE;
11907  break;
11908  }
11909  }
11910  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11911 
11912  if( !redundant )
11913  {
11914  if( hasrhs )
11915  {
11916  /* determine the remainder of the right hand side and the gcd */
11917  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11918  }
11919  else
11920  {
11921  /* determine the remainder of the left hand side and the gcd */
11922  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11923  if( SCIPisZero(scip, siderest) )
11924  siderest = gcd;
11925  }
11926  }
11927  else
11928  ++v;
11929 
11930  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",
11931  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11932 
11933  /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11934  * reasonable absolute values */
11935  numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11936  REALABS(minactsub) < MAXACTVAL;
11937 
11938  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11939  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11940 
11941  /* check if we can remove redundant variables */
11942  if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11943  {
11944  SCIP_Real oldcoef;
11945 
11946  /* double check the redundancy */
11947 #ifndef NDEBUG
11948  SCIP_Real tmpminactsub = 0.0;
11949  SCIP_Real tmpmaxactsub = 0.0;
11950 
11951  /* recompute residual activities */
11952  for( w = v; w < nvars; ++w )
11953  {
11954  lb = SCIPvarGetLbGlobal(vars[w]);
11955  ub = SCIPvarGetUbGlobal(vars[w]);
11956 
11957  assert(!SCIPisInfinity(scip, -lb));
11958  assert(!SCIPisInfinity(scip, ub));
11959 
11960  /* update residual activities */
11961  if( vals[w] > 0 )
11962  {
11963  tmpmaxactsub += ub * vals[w];
11964  tmpminactsub += lb * vals[w];
11965  }
11966  else
11967  {
11968  tmpmaxactsub += lb * vals[w];
11969  tmpminactsub += ub * vals[w];
11970  }
11971  assert(tmpmaxactsub >= tmpminactsub);
11972  }
11973 
11974  if( hasrhs )
11975  {
11976  assert(offsetv == -1);
11977 
11978  /* determine the remainder of the right hand side and the gcd */
11979  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11980  }
11981  else
11982  {
11983  /* determine the remainder of the left hand side and the gcd */
11984  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11985  if( SCIPisZero(scip, siderest) )
11986  siderest = gcd;
11987  }
11988 
11989  /* is the redundancy really fulfilled */
11990  assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11991  (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11992 #endif
11993 
11994  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11995  nvars - v, SCIPconsGetName(cons));
11996 
11997  /* remove redundant variables */
11998  for( w = nvars - 1; w >= v; --w )
11999  {
12000  SCIP_CALL( delCoefPos(scip, cons, w) );
12001  }
12002  (*nchgcoefs) += (nvars - v);
12003 
12004  assert(w >= 0);
12005 
12006  oldcoef = vals[w];
12007 
12008  /* normalize constraint */
12009  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12010  assert(vars == consdata->vars);
12011  assert(vals == consdata->vals);
12012  assert(w < consdata->nvars);
12013 
12014  if( *infeasible )
12015  return SCIP_OKAY;
12016 
12017  /* compute new greatest common divisor due to normalization */
12018  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12019  assert(gcd >= 1);
12020 
12021  /* update side */
12022  if( hasrhs )
12023  {
12024  /* replace old with new right hand side */
12025  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12026  rhs = consdata->rhs;
12027  }
12028  else
12029  {
12030  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12031  {
12032  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12033  lhs = consdata->lhs;
12034  }
12035  else
12036  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12037  }
12038  ++(*nchgsides);
12039 
12040  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12041  assert(!haslhs || !SCIPisNegative(scip, lhs));
12042 
12043  /* get new constraint data */
12044  nvars = consdata->nvars;
12045  assert(nvars > 0);
12046 
12047  allcoefintegral = TRUE;
12048 
12049 #ifndef NDEBUG
12050  /* check integrality */
12051  for( w = offsetv + 1; w < nvars; ++w )
12052  {
12053  assert(SCIPisIntegral(scip, vals[w]));
12054  }
12055 #endif
12056  SCIPdebugPrintCons(scip, cons, NULL);
12057  }
12058 
12059  /* try to find a better gcd, when having large coefficients */
12060  if( offsetv >= 0 && gcd == 1 )
12061  {
12062  /* calculate greatest common divisor for all general variables */
12063  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12064 
12065  if( gcd > 1 )
12066  {
12067  gcd = -1;
12068  candpos = -1;
12069 
12070  for( v = nvars - 1; v > offsetv; --v )
12071  {
12072  assert(!SCIPisZero(scip, vals[v]));
12073  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
12074  break;
12075 
12076  if( !SCIPisIntegral(scip, vals[v]) )
12077  {
12078  allcoefintegral = FALSE;
12079  break;
12080  }
12081 
12082  oldgcd = gcd;
12083 
12084  if( gcd == -1 )
12085  {
12086  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12087  assert(gcd >= 1);
12088  }
12089  else
12090  {
12091  /* calculate greatest common divisor for all general and binary variables */
12092  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12093  }
12094 
12095  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12096  * can stop searching
12097  */
12098  if( gcd == 1 )
12099  {
12100  if( !SCIPvarIsBinary(vars[v]) )
12101  break;
12102 
12103  /* found candidate */
12104  if( candpos == -1 )
12105  {
12106  gcd = oldgcd;
12107  candpos = v;
12108  }
12109  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12110  else
12111  break;
12112  }
12113  }
12114  assert(v > offsetv || candpos > offsetv);
12115  }
12116  else
12117  candpos = -1;
12118  }
12119  else
12120  candpos = nvars - 1;
12121 
12122  /* check last coefficient for integrality */
12123  if( gcd > 1 && allcoefintegral && !redundant )
12124  {
12125  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12126  allcoefintegral = FALSE;
12127  }
12128 
12129  /* check for further necessary coefficient adjustments */
12130  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12131  {
12132  assert(offsetv + 1 < nvars);
12133  assert(0 <= candpos && candpos < nvars);
12134 
12135  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12136  {
12137  SCIP_Bool notchangable = FALSE;
12138 
12139 #ifndef NDEBUG
12140  /* check integrality */
12141  for( w = offsetv + 1; w < nvars; ++w )
12142  {
12143  assert(SCIPisIntegral(scip, vals[w]));
12144  }
12145 #endif
12146 
12147  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12148  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12149  {
12150  /* determine the remainder of the side and the gcd */
12151  if( hasrhs )
12152  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12153  else
12154  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12155  assert(rest >= 0);
12156  assert(rest < gcd);
12157 
12158  /* determine the remainder of the coefficient candidate and the gcd */
12159  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12160  assert(restcoef >= 1);
12161  assert(restcoef < gcd);
12162 
12163  if( hasrhs )
12164  {
12165  /* calculate new coefficient */
12166  if( restcoef > rest )
12167  newcoef = vals[candpos] - restcoef + gcd;
12168  else
12169  newcoef = vals[candpos] - restcoef;
12170  }
12171  else
12172  {
12173  /* calculate new coefficient */
12174  if( rest == 0 || restcoef < rest )
12175  newcoef = vals[candpos] - restcoef;
12176  else
12177  newcoef = vals[candpos] - restcoef + gcd;
12178  }
12179 
12180  /* done */
12181 
12182  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12183  * another with the big coefficient was set to 1
12184  */
12185  if( hasrhs && SCIPisZero(scip, newcoef) )
12186  {
12187  notchangable = TRUE;
12188  }
12189  else if( SCIPisZero(scip, newcoef) )
12190  {
12191  /* delete old redundant coefficient */
12192  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12193  ++(*nchgcoefs);
12194  }
12195  else
12196  {
12197  /* replace old with new coefficient */
12198  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12199  ++(*nchgcoefs);
12200  }
12201  }
12202  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12203  {
12204  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12205  }
12206 
12207  /* correct side and big coefficients */
12208  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12209  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12210  {
12211  if( haslhs )
12212  {
12213  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12214 
12215  SCIP_CALL( chgLhs(scip, cons, newcoef) );
12216  ++(*nchgsides);
12217  }
12218  else
12219  {
12220  assert(hasrhs);
12221  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12222 
12223  SCIP_CALL( chgRhs(scip, cons, newcoef) );
12224  ++(*nchgsides);
12225  }
12226 
12227  /* correct coefficients up front */
12228  for( w = offsetv; w >= 0; --w )
12229  {
12230  assert(vals[w] > 0);
12231 
12232  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12233  }
12234  (*nchgcoefs) += (offsetv + 1);
12235  }
12236 
12237  if( !notchangable )
12238  {
12239  /* normalize constraint */
12240  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12241  assert(vars == consdata->vars);
12242  assert(vals == consdata->vals);
12243 
12244  if( *infeasible )
12245  return SCIP_OKAY;
12246 
12247  /* get new constraint data */
12248  nvars = consdata->nvars;
12249  assert(nvars >= 2);
12250 
12251  SCIPdebugPrintCons(scip, cons, NULL);
12252 
12253  lhs = consdata->lhs;
12254  rhs = consdata->rhs;
12255  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12256  assert(!haslhs || !SCIPisNegative(scip, lhs));
12257  }
12258  }
12259  }
12260  }
12261 
12262  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12263  /* no continuous variables are left over */
12264  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12265  return SCIP_OKAY;
12266 
12267  onlybin = TRUE;
12268  allcoefintegral = TRUE;
12269  /* check if all variables are of binary type */
12270  for( v = nvars - 1; v >= 0; --v )
12271  {
12272  if( !SCIPvarIsBinary(vars[v]) )
12273  onlybin = FALSE;
12274  if( !SCIPisIntegral(scip, vals[v]) )
12275  allcoefintegral = FALSE;
12276  }
12277 
12278  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12279  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12280  *
12281  * @todo there are some steps missing ....
12282  */
12283  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12284  {
12285  SCIP_Real val;
12286  SCIP_Real newval;
12287  SCIP_Real frac = 0.0;
12288  SCIP_Bool found = FALSE;
12289 
12290  if( hasrhs )
12291  {
12292  if( allcoefintegral )
12293  {
12294  /* replace old with new right hand side */
12295  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12296  ++(*nchgsides);
12297  }
12298  else
12299  {
12300  siderest = rhs - SCIPfloor(scip, rhs);
12301 
12302  /* try to round down all non-integral coefficients */
12303  for( v = nvars - 1; v >= 0; --v )
12304  {
12305  val = vals[v];
12306 
12307  /* add up all possible fractional parts */
12308  if( !SCIPisIntegral(scip, val) )
12309  {
12310  lb = SCIPvarGetLbGlobal(vars[v]);
12311  ub = SCIPvarGetUbGlobal(vars[v]);
12312 
12313  /* at least one bound need to be at zero */
12314  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12315  return SCIP_OKAY;
12316 
12317  /* swap bounds for 'standard' form */
12318  if( !SCIPisFeasZero(scip, lb) )
12319  {
12320  ub = lb;
12321  val *= -1;
12322  }
12323 
12324  found = TRUE;
12325 
12326  frac += (val - SCIPfloor(scip, val)) * ub;
12327 
12328  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12329  *
12330  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12331  * x3, x4 set to 1 would be infeasible but feasible after flooring
12332  */
12333  if( SCIPisGT(scip, frac, siderest) )
12334  return SCIP_OKAY;
12335  }
12336  }
12337  assert(v == -1);
12338 
12339  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12340 
12341  /* round rhs and coefficients to integral values */
12342  if( found )
12343  {
12344  for( v = nvars - 1; v >= 0; --v )
12345  {
12346  val = vals[v];
12347 
12348  /* add the whole fractional part */
12349  if( !SCIPisIntegral(scip, val) )
12350  {
12351  lb = SCIPvarGetLbGlobal(vars[v]);
12352 
12353  if( SCIPisFeasZero(scip, lb) )
12354  newval = SCIPfloor(scip, val);
12355  else
12356  newval = SCIPceil(scip, val);
12357 
12358  if( SCIPisZero(scip, newval) )
12359  {
12360  /* delete old redundant coefficient */
12361  SCIP_CALL( delCoefPos(scip, cons, v) );
12362  ++(*nchgcoefs);
12363  }
12364  else
12365  {
12366  /* replace old with new coefficient */
12367  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12368  ++(*nchgcoefs);
12369  }
12370  }
12371  }
12372  }
12373 
12374  /* replace old with new right hand side */
12375  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12376  ++(*nchgsides);
12377  }
12378  }
12379  else
12380  {
12381  if( allcoefintegral )
12382  {
12383  /* replace old with new left hand side */
12384  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12385  ++(*nchgsides);
12386  }
12387  else
12388  {
12389  /* cannot floor left hand side to zero */
12390  if( SCIPisLT(scip, lhs, 1.0) )
12391  return SCIP_OKAY;
12392 
12393  siderest = lhs - SCIPfloor(scip, lhs);
12394 
12395  /* try to round down all non-integral coefficients */
12396  for( v = nvars - 1; v >= 0; --v )
12397  {
12398  val = vals[v];
12399 
12400  /* add up all possible fractional parts */
12401  if( !SCIPisIntegral(scip, val) )
12402  {
12403  lb = SCIPvarGetLbGlobal(vars[v]);
12404  ub = SCIPvarGetUbGlobal(vars[v]);
12405 
12406  /* at least one bound need to be at zero */
12407  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12408  return SCIP_OKAY;
12409 
12410  /* swap bounds for 'standard' form */
12411  if( !SCIPisFeasZero(scip, lb) )
12412  {
12413  ub = lb;
12414  val *= -1;
12415  }
12416 
12417  /* cannot floor to zero */
12418  if( SCIPisLT(scip, val, 1.0) )
12419  return SCIP_OKAY;
12420 
12421  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12422  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12423  return SCIP_OKAY;
12424 
12425  found = TRUE;
12426 
12427  frac += (val - SCIPfloor(scip, val)) * ub;
12428 
12429  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12430  * fractional parts of the variables, we cannot tighten the coefficients
12431  *
12432  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12433  * x2-x4 set to 1 would be feasible but not after flooring
12434  */
12435  if( SCIPisGE(scip, frac, 1 + siderest) )
12436  return SCIP_OKAY;
12437  }
12438  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12439  else
12440  return SCIP_OKAY;
12441  }
12442  assert(v == -1);
12443 
12444  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12445 
12446  /* round lhs and coefficients to integral values */
12447  if( found )
12448  {
12449  for( v = nvars - 1; v >= 0; --v )
12450  {
12451  val = vals[v];
12452 
12453  /* add the whole fractional part */
12454  if( !SCIPisIntegral(scip, val) )
12455  {
12456  lb = SCIPvarGetLbGlobal(vars[v]);
12457 
12458  if( SCIPisFeasZero(scip, lb) )
12459  newval = SCIPfloor(scip, val);
12460  else
12461  newval = SCIPceil(scip, val);
12462 
12463  if( SCIPisZero(scip, newval) )
12464  {
12465  /* delete old redundant coefficient */
12466  SCIP_CALL( delCoefPos(scip, cons, v) );
12467  ++(*nchgcoefs);
12468  }
12469  else
12470  {
12471  /* replace old with new coefficient */
12472  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12473  ++(*nchgcoefs);
12474  }
12475  }
12476  }
12477  }
12478 
12479  /* replace old with new left hand side */
12480  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12481  ++(*nchgsides);
12482  }
12483  }
12484 
12485  /* normalize constraint */
12486  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12487  assert(vars == consdata->vars);
12488  assert(vals == consdata->vals);
12489 
12490  if( *infeasible )
12491  return SCIP_OKAY;
12492 
12493  rhs = consdata->rhs;
12494  lhs = consdata->lhs;
12495 
12496  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12497  assert(!haslhs || !SCIPisNegative(scip, lhs));
12498 
12499  SCIPdebugPrintCons(scip, cons, NULL);
12500 
12501  nvars = consdata->nvars;
12502  if( nvars < 2 )
12503  return SCIP_OKAY;
12504 
12505  allcoefintegral = TRUE;
12506 #ifndef NDEBUG
12507  /* debug check if all coefficients are really integral */
12508  for( v = nvars - 1; v >= 0; --v )
12509  assert(SCIPisIntegral(scip, vals[v]));
12510 #endif
12511  }
12512 
12513  /* @todo following can also work on non integral coefficients, need more investigation */
12514  /* only check constraints with integral coefficients on all integral variables */
12515  if( !allcoefintegral )
12516  return SCIP_OKAY;
12517 
12518  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12519  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12520  return SCIP_OKAY;
12521 
12522  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12523  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12524  return SCIP_OKAY;
12525 
12526  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12527  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12528  return SCIP_OKAY;
12529 
12530  assert(nvars >= 2);
12531 
12532  /* start gcd procedure for all variables */
12533  do
12534  {
12535  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12536  SCIPdebug( oldnchgsides = *nchgsides; )
12537 
12538  /* stop if we have two coeffcients which are one in absolute value */
12539  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12540  return SCIP_OKAY;
12541 
12542  gcd = -1;
12543 
12544  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12545  * because coefficients of non-binary variables might have changed to zero */
12546  if( !onlybin )
12547  {
12548  foundbin = -1;
12549  onlybin = TRUE;
12550 
12551  for( v = nvars - 1; v >= 0; --v )
12552  {
12553  assert(!SCIPisZero(scip, vals[v]));
12554  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12555 
12556  if( SCIPvarIsBinary(vars[v]) )
12557  {
12558  if( foundbin == -1 )
12559  foundbin = v;
12560  continue;
12561  }
12562  else
12563  onlybin = FALSE;
12564 
12565  absval = REALABS(vals[v]);
12566  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12567  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12568  */
12569  assert(SCIPisFeasIntegral(scip, absval));
12570 
12571  if( gcd == -1 )
12572  {
12573  gcd = (SCIP_Longint)(absval + feastol);
12574  assert(gcd >= 1);
12575  }
12576  else
12577  {
12578  /* calculate greatest common divisor for all general variables */
12579  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12580  }
12581  if( gcd == 1 )
12582  break;
12583  }
12584  }
12585  else
12586  foundbin = nvars - 1;
12587 
12588  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12589  if( gcd == 1 || foundbin == -1)
12590  return SCIP_OKAY;
12591 
12592  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12593 
12594  candpos = -1;
12595  candpos2 = -1;
12596 
12597  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12598  * change the coefficient
12599  */
12600  for( v = foundbin; v >= 0; --v )
12601  {
12602  if( onlybin || SCIPvarIsBinary(vars[v]) )
12603  {
12604  absval = REALABS(vals[v]);
12605  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12606  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12607  */
12608  assert(SCIPisFeasIntegral(scip, absval));
12609 
12610  oldgcd = gcd;
12611 
12612  if( gcd == -1 )
12613  {
12614  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12615  assert(gcd >= 1);
12616  }
12617  else
12618  {
12619  /* calculate greatest common divisor for all general and binary variables */
12620  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12621  }
12622 
12623  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12624  * can terminate
12625  */
12626  if( gcd == 1 )
12627  {
12628  /* found candidate */
12629  if( candpos == -1 )
12630  {
12631  gcd = oldgcd;
12632  candpos = v;
12633 
12634  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12635  * the coefficient change
12636  */
12637  if( onlybin && v == foundbin - 1 )
12638  candpos2 = foundbin;
12639  }
12640  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12641  else
12642  {
12643  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12644  {
12645  assert(candpos2 == nvars - 1);
12646 
12647  /* take new candidates */
12648  candpos = candpos2;
12649 
12650  /* recalculate gcd from scratch */
12651  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12652  assert(gcd >= 1);
12653 
12654  /* calculate greatest common divisor for all general and binary variables */
12655  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12656  if( gcd == 1 )
12657  return SCIP_OKAY;
12658  }
12659  else
12660  /* cannot determine a possible coefficient for reduction */
12661  return SCIP_OKAY;
12662  }
12663  }
12664  }
12665  }
12666  assert(gcd >= 2);
12667 
12668  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12669  * further
12670  */
12671  assert(candpos >= 0 && candpos < nvars);
12672 
12673  /* all variables and all coefficients are integral, so the side should be too */
12674  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12675 
12676  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12677  * @see normalizeCons()
12678  */
12679  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12680  assert(!haslhs || !SCIPisNegative(scip, lhs));
12681 
12682  /* determine the remainder of the side and the gcd */
12683  if( hasrhs )
12684  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12685  else
12686  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12687  assert(rest >= 0);
12688  assert(rest < gcd);
12689 
12690  /* determine the remainder of the coefficient candidate and the gcd */
12691  if( vals[candpos] < 0 )
12692  {
12693  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12694  assert(restcoef <= -1);
12695  restcoef += gcd;
12696  }
12697  else
12698  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12699  assert(restcoef >= 1);
12700  assert(restcoef < gcd);
12701 
12702  if( hasrhs )
12703  {
12704  if( rest > 0 )
12705  {
12706  /* replace old with new right hand side */
12707  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12708  ++(*nchgsides);
12709  }
12710 
12711  /* calculate new coefficient */
12712  if( restcoef > rest )
12713  newcoef = vals[candpos] - restcoef + gcd;
12714  else
12715  newcoef = vals[candpos] - restcoef;
12716  }
12717  else
12718  {
12719  if( rest > 0 )
12720  {
12721  /* replace old with new left hand side */
12722  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12723  ++(*nchgsides);
12724  }
12725 
12726  /* calculate new coefficient */
12727  if( rest == 0 || restcoef < rest )
12728  newcoef = vals[candpos] - restcoef;
12729  else
12730  newcoef = vals[candpos] - restcoef + gcd;
12731  }
12732  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12733 
12734  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));
12735 
12736  if( SCIPisZero(scip, newcoef) )
12737  {
12738  /* delete redundant coefficient */
12739  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12740  }
12741  else
12742  {
12743  /* replace old with new coefficient */
12744  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12745  }
12746  ++(*nchgcoefs);
12747 
12748  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12749  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12750  assert(vars == consdata->vars);
12751  assert(vals == consdata->vals);
12752 
12753  if( *infeasible )
12754  return SCIP_OKAY;
12755 
12756  SCIPdebugPrintCons(scip, cons, NULL);
12757 
12758  rhs = consdata->rhs;
12759  lhs = consdata->lhs;
12760  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12761  assert(!haslhs || !SCIPisNegative(scip, lhs));
12762 
12763  nvars = consdata->nvars;
12764 
12765  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));
12766  }
12767  while( nvars >= 2 );
12768 
12769  return SCIP_OKAY;
12770 }
12771 
12772 
12773 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12774  * cons0 := a * cons0 + b * cons1,
12775  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12776  * for numerical stability, we will only accept integral a and b;
12777  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12778  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12779  */
12780 static
12782  SCIP* scip, /**< SCIP data structure */
12783  SCIP_CONS* cons0, /**< (in)equality to modify */
12784  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12785  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12786  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12787  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12788  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12789  int nvarscommon, /**< number of variables, that appear in both constraints */
12790  int commonidxweight, /**< variable weight sum of common variables */
12791  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12792  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12793  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12794  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12795  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12796  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12797  )
12798 {
12799  SCIP_CONSDATA* consdata0;
12800  SCIP_CONSDATA* consdata1;
12801  SCIP_Real a;
12802  SCIP_Real b;
12803  SCIP_Real aggrcoef;
12804  SCIP_Real scalarsum;
12805  SCIP_Real bestscalarsum;
12806  SCIP_Bool betterscalarsum;
12807  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12808  int varweight;
12809  int nvars;
12810  int bestvarweight;
12811  int bestnvars;
12812  int bestv;
12813  int v;
12814  int i;
12815 
12816  assert(scip != NULL);
12817  assert(cons0 != NULL);
12818  assert(cons1 != NULL);
12819  assert(commonidx0 != NULL);
12820  assert(commonidx1 != NULL);
12821  assert(diffidx0minus1 != NULL);
12822  assert(diffidx1minus0 != NULL);
12823  assert(nvarscommon >= 1);
12824  assert(commonidxweight >= nvarscommon);
12825  assert(nchgcoefs != NULL);
12826  assert(aggregated != NULL);
12827 
12828  assert(SCIPconsIsActive(cons0));
12829  assert(SCIPconsIsActive(cons1));
12830 
12831  *infeasible = FALSE;
12832 
12833  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12834 
12835  /* cons0 is an (in)equality */
12836  consdata0 = SCIPconsGetData(cons0);
12837  assert(consdata0 != NULL);
12838  assert(consdata0->nvars >= 1);
12839  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12840  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12841 
12842  /* cons1 is an equality */
12843  consdata1 = SCIPconsGetData(cons1);
12844  assert(consdata1 != NULL);
12845  assert(consdata1->nvars >= 1);
12846  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12847  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12848 
12849  *aggregated = FALSE;
12850 
12851  /* search for the best common variable such that
12852  * val1[var] * consdata0 - val0[var] * consdata1
12853  * has least weighted number of variables
12854  */
12855  bestvarweight = commonidxweight + diffidx0minus1weight;
12856  bestnvars = consdata0->nvars;
12857  bestv = -1;
12858  bestscalarsum = 0.0;
12859  commonvarlindependent = TRUE;
12860  for( v = 0; v < nvarscommon; ++v )
12861  {
12862  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12863  a = consdata1->vals[commonidx1[v]];
12864  b = -consdata0->vals[commonidx0[v]];
12865 
12866  /* only try aggregation, if coefficients are integral (numerical stability) */
12867  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12868  {
12869  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12870  varweight = diffidx0minus1weight + diffidx1minus0weight;
12871  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12872  scalarsum = REALABS(a) + REALABS(b);
12873  betterscalarsum = (scalarsum < bestscalarsum);
12874  for( i = 0; i < nvarscommon
12875  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12876  {
12877  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12878  if( !SCIPisZero(scip, aggrcoef) )
12879  {
12880  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12881  nvars++;
12882  }
12883  }
12884  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12885  {
12886  bestv = v;
12887  bestvarweight = varweight;
12888  bestnvars = nvars;
12889  bestscalarsum = scalarsum;
12890  }
12891  }
12892 
12893  /* update commonvarlindependent flag, if still TRUE:
12894  * 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
12895  */
12896  if( commonvarlindependent && v > 0 )
12897  commonvarlindependent = SCIPisEQ(scip,
12898  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12899  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12900  }
12901 
12902  /* if better aggregation was found, create new constraint and delete old one */
12903  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12904  {
12905  SCIP_CONS* newcons;
12906  SCIP_CONSDATA* newconsdata;
12907  SCIP_VAR** newvars;
12908  SCIP_Real* newvals;
12909  SCIP_Real newlhs;
12910  SCIP_Real newrhs;
12911  int newnvars;
12912 
12913  if( bestv != -1 )
12914  {
12915  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12916  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12917  {
12918  a = consdata1->vals[commonidx1[bestv]];
12919  b = -consdata0->vals[commonidx0[bestv]];
12920  }
12921  else
12922  {
12923  a = -consdata1->vals[commonidx1[bestv]];
12924  b = consdata0->vals[commonidx0[bestv]];
12925  }
12926  assert(SCIPisIntegral(scip, a));
12927  assert(SCIPisPositive(scip, a));
12928  assert(SCIPisIntegral(scip, b));
12929  assert(!SCIPisZero(scip, b));
12930  }
12931  else
12932  {
12933  assert(commonvarlindependent);
12934  if( consdata1->vals[commonidx1[0]] > 0.0 )
12935  {
12936  a = consdata1->vals[commonidx1[0]];
12937  b = -consdata0->vals[commonidx0[0]];
12938  }
12939  else
12940  {
12941  a = -consdata1->vals[commonidx1[0]];
12942  b = consdata0->vals[commonidx0[0]];
12943  }
12944  assert(SCIPisPositive(scip, a));
12945  assert(!SCIPisZero(scip, b));
12946 
12947  /* if a/b is integral, then we can easily choose integer multipliers */
12948  if( SCIPisIntegral(scip, a/b) )
12949  {
12950  if( a/b > 0 )
12951  {
12952  a /= b;
12953  b = 1.0;
12954  }
12955  else
12956  {
12957  a /= -b;
12958  b = -1.0;
12959  }
12960  }
12961 
12962  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12963  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12964  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12965  }
12966 
12967  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12968  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12969  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12970  SCIPdebugPrintCons(scip, cons0, NULL);
12971  SCIPdebugPrintCons(scip, cons1, NULL);
12972 
12973  /* get temporary memory for creating the new linear constraint */
12974  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12975  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12976 
12977  /* calculate the common coefficients, if we have not recognized linear dependency */
12978  newnvars = 0;
12979  if( !commonvarlindependent )
12980  {
12981  for( i = 0; i < nvarscommon; ++i )
12982  {
12983  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12984  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12985 
12986  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12987  if( !SCIPisZero(scip, aggrcoef) )
12988  {
12989  assert(newnvars < bestnvars);
12990  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12991  newvals[newnvars] = aggrcoef;
12992  newnvars++;
12993  }
12994  }
12995  }
12996  else
12997  {
12998  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12999 #ifndef NDEBUG
13000  for( i = 0; i < nvarscommon; ++i )
13001  {
13002  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
13003  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
13004 
13005  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
13006  assert(SCIPisZero(scip, aggrcoef));
13007  }
13008 #endif
13009  }
13010 
13011  /* calculate the coefficients appearing in cons0 but not in cons1 */
13012  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
13013  {
13014  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13015 
13016  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13017  assert(!SCIPisZero(scip, aggrcoef));
13018  assert(newnvars < bestnvars);
13019  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13020  newvals[newnvars] = aggrcoef;
13021  newnvars++;
13022  }
13023 
13024  /* calculate the coefficients appearing in cons1 but not in cons0 */
13025  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13026  {
13027  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13028 
13029  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13030  assert(!SCIPisZero(scip, aggrcoef));
13031  assert(newnvars < bestnvars);
13032  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13033  newvals[newnvars] = aggrcoef;
13034  newnvars++;
13035  }
13036  assert(newnvars == bestnvars);
13037 
13038  /* calculate the new left and right hand side of the (in)equality */
13039  assert(!SCIPisInfinity(scip, -consdata1->lhs));
13040  assert(!SCIPisInfinity(scip, consdata1->rhs));
13041  if( SCIPisInfinity(scip, -consdata0->lhs) )
13042  newlhs = -SCIPinfinity(scip);
13043  else
13044  newlhs = a * consdata0->lhs + b * consdata1->lhs;
13045  if( SCIPisInfinity(scip, consdata0->rhs) )
13046  newrhs = SCIPinfinity(scip);
13047  else
13048  newrhs = a * consdata0->rhs + b * consdata1->rhs;
13049 
13050  /* create the new linear constraint */
13051  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13053  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
13054  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
13056 
13057  newconsdata = SCIPconsGetData(newcons);
13058  assert(newconsdata != NULL);
13059 
13060  /* copy the upgraded flag from the old cons0 to the new constraint */
13061  newconsdata->upgraded = consdata0->upgraded;
13062 
13063  /* normalize the new constraint */
13064  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13065 
13066  if( *infeasible )
13067  goto TERMINATE;
13068 
13069  /* check, if we really want to use the new constraint instead of the old one:
13070  * use the new one, if the maximum norm doesn't grow too much
13071  */
13072  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13073  {
13074  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13075  SCIPdebugPrintCons(scip, newcons, NULL);
13076 
13077  /* update the statistics: we changed all coefficients */
13078  if( !consdata0->upgraded )
13079  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13080  *aggregated = TRUE;
13081 
13082  /* delete the old constraint, and add the new linear constraint to the problem */
13083  SCIP_CALL( SCIPdelCons(scip, cons0) );
13084  SCIP_CALL( SCIPaddCons(scip, newcons) );
13085  }
13086 
13087  TERMINATE:
13088  /* release the new constraint */
13089  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13090 
13091  /* free temporary memory */
13092  SCIPfreeBufferArray(scip, &newvals);
13093  SCIPfreeBufferArray(scip, &newvars);
13094  }
13095 
13096  return SCIP_OKAY;
13097 }
13098 
13099 /** gets the key of the given element */
13100 static
13101 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13102 { /*lint --e{715}*/
13103  /* the key is the element itself */
13104  return elem;
13105 }
13106 
13107 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13108  * coefficients are either equal or negated
13109  */
13110 static
13111 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13112 {
13113  SCIP* scip;
13114  SCIP_CONSDATA* consdata1;
13115  SCIP_CONSDATA* consdata2;
13116  SCIP_Real cons1scale;
13117  SCIP_Real cons2scale;
13118  int i;
13119 
13120  assert(key1 != NULL);
13121  assert(key2 != NULL);
13122  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13123  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13124  assert(consdata1->indexsorted);
13125  assert(consdata2->indexsorted);
13126 
13127  scip = (SCIP*)userptr;
13128  assert(scip != NULL);
13129 
13130  /* if it is the same constraint we dont need to check anything */
13131  if( key1 == key2 )
13132  return TRUE;
13133 
13134  /* checks trivial case */
13135  if( consdata1->nvars != consdata2->nvars )
13136  return FALSE;
13137 
13138  /* tests if variables are equal */
13139  for( i = 0; i < consdata1->nvars; ++i )
13140  {
13141  if( consdata1->vars[i] != consdata2->vars[i] )
13142  {
13143  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13144  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13145  return FALSE;
13146  }
13147  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13148  }
13149 
13150  /* compute scale before comparing coefficients of constraints */
13151  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13152  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13153 
13154  /* tests if coefficients are equal with the computed scale */
13155  for( i = 0; i < consdata1->nvars; ++i )
13156  {
13157  SCIP_Real val1;
13158  SCIP_Real val2;
13159 
13160  val1 = consdata1->vals[i] * cons1scale;
13161  val2 = consdata2->vals[i] * cons2scale;
13162 
13163  if( !SCIPisEQ(scip, val1, val2) )
13164  return FALSE;
13165  }
13166 
13167  return TRUE;
13168 }
13169 
13170 /** returns the hash value of the key */
13171 static
13172 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13173 {
13174  SCIP_CONSDATA* consdata;
13175  int minidx;
13176  int mididx;
13177  int maxidx;
13178  SCIP_Real scale;
13179 #ifndef NDEBUG
13180  SCIP* scip;
13181 
13182  scip = (SCIP*)userptr;
13183  assert(scip != NULL);
13184 #endif
13185 
13186  assert(key != NULL);
13187  consdata = SCIPconsGetData((SCIP_CONS*)key);
13188  assert(consdata != NULL);
13189  assert(consdata->nvars > 0);
13190 
13191  assert(consdata->indexsorted);
13192 
13193  minidx = SCIPvarGetIndex(consdata->vars[0]);
13194  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13195  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13196  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13197 
13198  /* using only the variable indices as hash, since the values are compared by epsilon */
13199  return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13200  mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13201  maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13202 }
13203 
13204 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13205  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13206  */
13207 static
13208 unsigned int getParallelConsKey(
13209  SCIP_CONS* cons /**< linear constraint */
13210  )
13211 {
13212  SCIP_CONSDATA* consdata;
13213 
13214  assert(cons != NULL);
13215 
13216  consdata = SCIPconsGetData(cons);
13217  assert(consdata != NULL);
13218 
13219  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13220 }
13221 
13222 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13223  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13224  * and all others are removed from the hashtable and stored in the given array
13225  */
13226 static
13228  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13229  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13230  * upon return will contain the constraint that should be kept */
13231  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13232  * these constraints where removed from the hashtable */
13233  int* nparallelconss /**< pointer to return number of parallel constraints */
13234  )
13235 {
13236  SCIP_CONS* parallelcons;
13237  unsigned int querykey;
13238 
13239  *nparallelconss = 0;
13240  querykey = getParallelConsKey(*querycons);
13241 
13242  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13243  {
13244  unsigned int conskey = getParallelConsKey(parallelcons);
13245 
13246  if( conskey < querykey )
13247  {
13248  parallelconss[(*nparallelconss)++] = *querycons;
13249  *querycons = parallelcons;
13250  querykey = conskey;
13251  }
13252  else
13253  {
13254  parallelconss[(*nparallelconss)++] = parallelcons;
13255  }
13256 
13257  /* if the constraint that just came out of the hash table is the one that is kept,
13258  * we do not need to look into the hashtable again, since the invariant is that
13259  * in the hashtable only pair-wise non-parallel constraints are contained.
13260  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13261  * could be contained due to non-transitivity of the equality comparison.
13262  * Also we can return immediately, since parallelcons is already contained in the
13263  * hashtable and we do not need to remove and reinsert it.
13264  */
13265  if( *querycons == parallelcons )
13266  return SCIP_OKAY;
13267 
13268  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13269  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13270  }
13271 
13272  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13273  * comnpares equal to querycons at this point
13274  */
13275 #ifndef NDEBUG
13276  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13277 #else
13278  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13279 #endif
13280 
13281  return SCIP_OKAY;
13282 }
13283 
13284 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13285  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13286  */
13287 static
13289  SCIP* scip, /**< SCIP data structure */
13290  BMS_BLKMEM* blkmem, /**< block memory */
13291  SCIP_CONS** conss, /**< constraint set */
13292  int nconss, /**< number of constraints in constraint set */
13293  int* firstchange, /**< pointer to store first changed constraint */
13294  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13295  int* ndelconss, /**< pointer to count number of deleted constraints */
13296  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13297  )
13298 {
13299  SCIP_HASHTABLE* hashtable;
13300  SCIP_CONS** parallelconss;
13301  int nparallelconss;
13302  int hashtablesize;
13303  int c;
13304 
13305  assert(scip != NULL);
13306  assert(blkmem != NULL);
13307  assert(conss != NULL);
13308  assert(firstchange != NULL);
13309  assert(cutoff != NULL);
13310  assert(ndelconss != NULL);
13311  assert(nchgsides != NULL);
13312 
13313  /* create a hash table for the constraint set */
13314  hashtablesize = nconss;
13315  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13316  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13317 
13318  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13319 
13320  /* check all constraints in the given set for redundancy */
13321  for( c = 0; c < nconss; ++c )
13322  {
13323  SCIP_CONS* cons0;
13324  SCIP_CONSDATA* consdata0;
13325 
13326  cons0 = conss[c];
13327 
13328  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13329  continue;
13330 
13331  /* do not check for parallel constraints if they should not be upgraded */
13332  if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13333  continue;
13334 
13335  /* check for interuption */
13336  if( c % 1000 == 0 && SCIPisStopped(scip) )
13337  break;
13338 
13339  /* sorts the constraint */
13340  consdata0 = SCIPconsGetData(cons0);
13341  assert(consdata0 != NULL);
13342  SCIP_CALL( consdataSort(scip, consdata0) );
13343  assert(consdata0->indexsorted);
13344 
13345  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13346  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13347  * first variable is positive
13348  * Also inserts cons0 into the hashtable.
13349  */
13350  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13351 
13352  if( nparallelconss != 0 )
13353  {
13354  SCIP_Real lhs;
13355  SCIP_Real rhs;
13356 
13357  int i;
13358 
13359  /* cons0 may have been changed in retrieveParallelConstraints() */
13360  consdata0 = SCIPconsGetData(cons0);
13361 
13362  lhs = consdata0->lhs;
13363  rhs = consdata0->rhs;
13364 
13365  for( i = 0; i < nparallelconss; ++i )
13366  {
13367  SCIP_CONS* consdel;
13368  SCIP_CONSDATA* consdatadel;
13369  SCIP_Real scale;
13370 
13371  consdel = parallelconss[i];
13372  consdatadel = SCIPconsGetData(consdel);
13373 
13374  /* do not delete constraint if it should not be upgraded */
13375  if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13376  continue;
13377 
13378  assert(SCIPconsIsActive(consdel));
13379  assert(!SCIPconsIsModifiable(consdel));
13380 
13381  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13382  * delete old constraints afterwards
13383  */
13384  assert(consdatadel != NULL);
13385  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13386 
13387  assert(consdatadel->indexsorted);
13388  assert(consdata0->vars[0] == consdatadel->vars[0]);
13389 
13390  scale = consdata0->vals[0] / consdatadel->vals[0];
13391  assert(scale != 0.0);
13392 
13393  /* in debug mode, check that all coefficients are equal with respect to epsilon
13394  * if the constraints are in equilibrium scale
13395  */
13396 #ifndef NDEBUG
13397  {
13398  int k;
13399  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13400  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13401 
13402  for( k = 0; k < consdata0->nvars; ++k )
13403  {
13404  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13405  }
13406  }
13407 #endif
13408 
13409  if( scale > 0.0 )
13410  {
13411  /* the coefficients of both constraints are parallel with a positive scale */
13412  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13413  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13414  SCIPdebugPrintCons(scip, cons0, NULL);
13415  SCIPdebugPrintCons(scip, consdel, NULL);
13416 
13417  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13418  lhs = MAX(scale * consdatadel->lhs, lhs);
13419 
13420  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13421  rhs = MIN(scale * consdatadel->rhs, rhs);
13422  }
13423  else
13424  {
13425  /* the coefficients of both rows are negations */
13426  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13427  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13428  SCIPdebugPrintCons(scip, cons0, NULL);
13429  SCIPdebugPrintCons(scip, consdel, NULL);
13430 
13431  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13432  lhs = MAX(scale * consdatadel->rhs, lhs);
13433 
13434  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13435  rhs = MIN(scale * consdatadel->lhs, rhs);
13436  }
13437 
13438  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13439  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13440 
13441  /* delete consdel */
13442  assert( ! consdata0->upgraded || consdatadel->upgraded );
13443  SCIP_CALL( SCIPdelCons(scip, consdel) );
13444  if( !consdatadel->upgraded )
13445  (*ndelconss)++;
13446  }
13447 
13448  if( SCIPisFeasLT(scip, rhs, lhs) )
13449  {
13450  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13451  *cutoff = TRUE;
13452  break;
13453  }
13454 
13455  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13456  if( lhs > rhs )
13457  {
13458  rhs = (lhs + rhs)/2;
13459  lhs = rhs;
13460  }
13461 
13462  /* update lhs and rhs of cons0 */
13463  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13464  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13465 
13466  /* update the first changed constraint to begin the next aggregation round with */
13467  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13468  *firstchange = SCIPconsGetPos(cons0);
13469 
13470  assert(SCIPconsIsActive(cons0));
13471  }
13472  }
13473 #ifdef SCIP_MORE_DEBUG
13474  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13476 #endif
13477 
13478  SCIPfreeBufferArray(scip, &parallelconss);
13479 
13480  /* free hash table */
13481  SCIPhashtableFree(&hashtable);
13482 
13483  return SCIP_OKAY;
13484 }
13485 
13486 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13487  * and removes or changes constraint accordingly
13488  */
13489 static
13491  SCIP* scip, /**< SCIP data structure */
13492  SCIP_CONS** conss, /**< constraint set */
13493  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13494  int chkind, /**< index of constraint to check against all prior indices upto startind */
13495  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13496  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13497  int* ndelconss, /**< pointer to count number of deleted constraints */
13498  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13499  int* nchgcoefs /**< pointer to count number of changed coefficients */
13500  )
13501 {
13502  SCIP_CONS* cons0;
13503  SCIP_CONSDATA* consdata0;
13504  int* commonidx0;
13505  int* commonidx1;
13506  int* diffidx0minus1;
13507  int* diffidx1minus0;
13508  uint64_t possignature0;
13509  uint64_t negsignature0;
13510  SCIP_Bool cons0changed;
13511  SCIP_Bool cons0isequality;
13512  int diffidx1minus0size;
13513  int c;
13514  SCIP_Real cons0lhs;
13515  SCIP_Real cons0rhs;
13516  SCIP_Bool cons0upgraded;
13517 
13518  assert(scip != NULL);
13519  assert(conss != NULL);
13520  assert(firstchange <= chkind);
13521  assert(cutoff != NULL);
13522  assert(ndelconss != NULL);
13523  assert(nchgsides != NULL);
13524  assert(nchgcoefs != NULL);
13525 
13526  /* get the constraint to be checked against all prior constraints */
13527  cons0 = conss[chkind];
13528  assert(cons0 != NULL);
13529  assert(SCIPconsIsActive(cons0));
13530  assert(!SCIPconsIsModifiable(cons0));
13531 
13532  consdata0 = SCIPconsGetData(cons0);
13533  assert(consdata0 != NULL);
13534  assert(consdata0->nvars >= 1);
13535  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13536 
13537  /* sort the constraint */
13538  SCIP_CALL( consdataSort(scip, consdata0) );
13539 
13540  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13541  consdataCalcSignatures(consdata0);
13542  possignature0 = consdata0->possignature;
13543  negsignature0 = consdata0->negsignature;
13544 
13545  /* get temporary memory for indices of common variables */
13546  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13547  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13548  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13549  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13550  diffidx1minus0size = consdata0->nvars;
13551 
13552  cons0lhs = consdata0->lhs;
13553  cons0rhs = consdata0->rhs;
13554  cons0upgraded = consdata0->upgraded;
13555 
13556  /* check constraint against all prior constraints */
13557  cons0changed = consdata0->changed;
13558  consdata0->changed = FALSE;
13559  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13560  {
13561  SCIP_CONS* cons1;
13562  SCIP_CONSDATA* consdata1;
13563  uint64_t possignature1;
13564  uint64_t negsignature1;
13565  SCIP_Bool cons0dominateslhs;
13566  SCIP_Bool cons1dominateslhs;
13567  SCIP_Bool cons0dominatesrhs;
13568  SCIP_Bool cons1dominatesrhs;
13569  SCIP_Bool cons1isequality;
13570  SCIP_Bool coefsequal;
13571  SCIP_Bool coefsnegated;
13572  SCIP_Bool tryaggregation;
13573  int nvarscommon;
13574  int nvars0minus1;
13575  int nvars1minus0;
13576  int commonidxweight;
13577  int diffidx0minus1weight;
13578  int diffidx1minus0weight;
13579  int v0;
13580  int v1;
13581 
13582  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13583  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13584  assert(cons0upgraded == consdata0->upgraded);
13585 
13586  cons1 = conss[c];
13587 
13588  /* cons1 has become inactive during presolving of constraint pairs */
13589  if( cons1 == NULL )
13590  continue;
13591 
13592  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13593  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13594 
13595  consdata1 = SCIPconsGetData(cons1);
13596  assert(consdata1 != NULL);
13597 
13598  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13599  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13600  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13601 
13602  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13603  if( !cons0changed && !consdata1->changed )
13604  continue;
13605 
13606  /* if both constraints are already upgraded, skip the pair;
13607  * because changes on these constraints cannot be applied to the instance anymore */
13608  if( cons0upgraded && consdata1->upgraded )
13609  continue;
13610 
13611  assert(consdata1->nvars >= 1);
13612 
13613  /* sort the constraint */
13614  SCIP_CALL( consdataSort(scip, consdata1) );
13615 
13616  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13617  consdataCalcSignatures(consdata1);
13618  possignature1 = consdata1->possignature;
13619  negsignature1 = consdata1->negsignature;
13620 
13621  /* the signatures give a quick test to check for domination and equality of coefficients */
13622  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13623  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13624  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13625  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13626  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13627  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13628  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13629  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13630  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13631  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13632  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13633  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13634  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13635  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13636  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13637  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13638  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13639  && !coefsequal && !coefsnegated && !tryaggregation )
13640  continue;
13641 
13642  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13643  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13644  {
13645  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13646  diffidx1minus0size = consdata1->nvars;
13647  }
13648 
13649  /* check consdata0 against consdata1:
13650  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13651  * consdata0 dominates consdata1 w.r.t. left hand side
13652  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13653  * consdata0 dominates consdata1 w.r.t. right hand side
13654  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13655  * ranged row (or equality)
13656  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13657  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13658  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13659  * number of continuous and integer variables are preferred:
13660  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13661  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13662  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13663  * to be positive to not switch the sense of the (in)equality cons0
13664  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13665  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13666  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13667  * to be positive to not switch the sense of the (in)equality cons1
13668  */
13669 
13670  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13671  nvarscommon = 0;
13672  commonidxweight = 0;
13673  nvars0minus1 = 0;
13674  diffidx0minus1weight = 0;
13675  nvars1minus0 = 0;
13676  diffidx1minus0weight = 0;
13677  v0 = 0;
13678  v1 = 0;
13679  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13680  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13681  || coefsequal || coefsnegated || tryaggregation) )
13682  {
13683  SCIP_VAR* var;
13684  SCIP_Real val0;
13685  SCIP_Real val1;
13686  int varcmp;
13687 
13688  /* test, if variable appears in only one or in both constraints */
13689  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13690  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13691  else if( v0 < consdata0->nvars )
13692  varcmp = -1;
13693  else
13694  varcmp = +1;
13695 
13696  switch( varcmp )
13697  {
13698  case -1:
13699  /* variable doesn't appear in consdata1 */
13700  var = consdata0->vars[v0];
13701  val0 = consdata0->vals[v0];
13702  val1 = 0.0;
13703  if( tryaggregation )
13704  {
13705  diffidx0minus1[nvars0minus1] = v0;
13706  nvars0minus1++;
13707  diffidx0minus1weight += getVarWeight(var);
13708  }
13709  v0++;
13710  coefsequal = FALSE;
13711  coefsnegated = FALSE;
13712  break;
13713 
13714  case +1:
13715  /* variable doesn't appear in consdata0 */
13716  var = consdata1->vars[v1];
13717  val0 = 0.0;
13718  val1 = consdata1->vals[v1];
13719  if( tryaggregation )
13720  {
13721  diffidx1minus0[nvars1minus0] = v1;
13722  nvars1minus0++;
13723  diffidx1minus0weight += getVarWeight(var);
13724  }
13725  v1++;
13726  coefsequal = FALSE;
13727  coefsnegated = FALSE;
13728  break;
13729 
13730  case 0:
13731  /* variable appears in both constraints */
13732  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13733  var = consdata0->vars[v0];
13734  val0 = consdata0->vals[v0];
13735  val1 = consdata1->vals[v1];
13736  if( tryaggregation )
13737  {
13738  commonidx0[nvarscommon] = v0;
13739  commonidx1[nvarscommon] = v1;
13740  nvarscommon++;
13741  commonidxweight += getVarWeight(var);
13742  }
13743  v0++;
13744  v1++;
13745  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13746  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13747  break;
13748 
13749  default:
13750  SCIPerrorMessage("invalid comparison result\n");
13751  SCIPABORT();
13752  var = NULL;
13753  val0 = 0.0;
13754  val1 = 0.0;
13755  }
13756  assert(var != NULL);
13757 
13758  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13759  if( SCIPisGT(scip, val0, val1) )
13760  {
13761  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13762  {
13763  cons0dominatesrhs = FALSE;
13764  cons1dominateslhs = FALSE;
13765  }
13766  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13767  {
13768  cons0dominateslhs = FALSE;
13769  cons1dominatesrhs = FALSE;
13770  }
13771  }
13772  else if( SCIPisLT(scip, val0, val1) )
13773  {
13774  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13775  {
13776  cons0dominateslhs = FALSE;
13777  cons1dominatesrhs = FALSE;
13778  }
13779  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13780  {
13781  cons0dominatesrhs = FALSE;
13782  cons1dominateslhs = FALSE;
13783  }
13784  }
13785  }
13786 
13787  /* check for disaggregated ranged rows */
13788  if( coefsequal || coefsnegated )
13789  {
13790  SCIP_CONS* consstay;
13791  SCIP_CONS* consdel;
13792 #ifndef NDEBUG
13793  SCIP_CONSDATA* consdatastay;
13794 #endif
13795  SCIP_CONSDATA* consdatadel;
13796  SCIP_Real lhs;
13797  SCIP_Real rhs;
13798  int consinddel;
13799 
13800  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13801  * best left and right hand sides; delete the old constraints afterwards
13802  */
13803  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13804  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13805  SCIPdebugPrintCons(scip, cons0, NULL);
13806  SCIPdebugPrintCons(scip, cons1, NULL);
13807 
13808  if( coefsequal )
13809  {
13810  /* the coefficients of both rows are equal */
13811  lhs = MAX(consdata0->lhs, consdata1->lhs);
13812  rhs = MIN(consdata0->rhs, consdata1->rhs);
13813  }
13814  else
13815  {
13816  /* the coefficients of both rows are negations */
13817  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13818  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13819  }
13820  if( SCIPisFeasLT(scip, rhs, lhs) )
13821  {
13822  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13823  *cutoff = TRUE;
13824  break;
13825  }
13826 
13827  /* check which constraint has to stay;
13828  * changes applied to an upgraded constraint will not be considered in the instance */
13829  if( consdata0->upgraded )
13830  {
13831  assert(!consdata1->upgraded);
13832  consstay = cons1;
13833 #ifndef NDEBUG
13834  consdatastay = consdata1;
13835 #endif
13836 
13837  consdel = cons0;
13838  consdatadel = consdata0;
13839  consinddel = chkind;
13840  }
13841  else
13842  {
13843  consstay = cons0;
13844 #ifndef NDEBUG
13845  consdatastay = consdata0;
13846 #endif
13847 
13848  consdel = cons1;
13849  consdatadel = consdata1;
13850  consinddel = c;
13851  }
13852 
13853  /* update the sides of consstay */
13854  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13855  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13856  if( !consdata0->upgraded )
13857  {
13858  assert(consstay == cons0);
13859  cons0lhs = consdata0->lhs;
13860  cons0rhs = consdata0->rhs;
13861  }
13862 
13863  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13864  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13865 
13866  assert( !consdatastay->upgraded );
13867  /* delete consdel */
13868  SCIP_CALL( SCIPdelCons(scip, consdel) );
13869  conss[consinddel] = NULL;
13870  if( !consdatadel->upgraded )
13871  (*ndelconss)++;
13872  continue;
13873  }
13874 
13875  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13876  * redundant
13877  */
13878  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13879  {
13880  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13881  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13882  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13883  SCIPdebugPrintCons(scip, cons0, NULL);
13884  SCIPdebugPrintCons(scip, cons1, NULL);
13885 
13886  /* check for infeasibility */
13887  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13888  {
13889  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13890  *cutoff = TRUE;
13891  break;
13892  }
13893 
13894  /* remove redundant left hand side */
13895  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13896  {
13897  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13898  cons0lhs = consdata0->lhs;
13899  cons0isequality = FALSE;
13900  if( !consdata0->upgraded )
13901  {
13902  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13903  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13904 
13905  (*nchgsides)++;
13906  }
13907  }
13908  }
13909  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13910  {
13911  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13912  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13913  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13914  SCIPdebugPrintCons(scip, cons1, NULL);
13915  SCIPdebugPrintCons(scip, cons0, NULL);
13916 
13917  /* check for infeasibility */
13918  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13919  {
13920  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13921  *cutoff = TRUE;
13922  break;
13923  }
13924 
13925  /* remove redundant left hand side */
13926  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13927  {
13928  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13929  cons1isequality = FALSE;
13930  if( !consdata1->upgraded )
13931  {
13932  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13933  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13934 
13935  (*nchgsides)++;
13936  }
13937  }
13938  }
13939  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13940  {
13941  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13942  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13943  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13944  SCIPdebugPrintCons(scip, cons0, NULL);
13945  SCIPdebugPrintCons(scip, cons1, NULL);
13946 
13947  /* check for infeasibility */
13948  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13949  {
13950  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13951  *cutoff = TRUE;
13952  break;
13953  }
13954 
13955  /* remove redundant right hand side */
13956  if( !SCIPisInfinity(scip, consdata0->rhs) )
13957  {
13958  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13959  cons0rhs = consdata0->rhs;
13960  cons0isequality = FALSE;
13961  if( !consdata0->upgraded )
13962  {
13963  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13964  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13965 
13966  (*nchgsides)++;
13967  }
13968  }
13969  }
13970  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13971  {
13972  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13973  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13974  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13975  SCIPdebugPrintCons(scip, cons1, NULL);
13976  SCIPdebugPrintCons(scip, cons0, NULL);
13977 
13978  /* check for infeasibility */
13979  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13980  {
13981  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13982  *cutoff = TRUE;
13983  break;
13984  }
13985 
13986  /* remove redundant right hand side */
13987  if( !SCIPisInfinity(scip, consdata1->rhs) )
13988  {
13989  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13990  cons1isequality = FALSE;
13991  if( !consdata1->upgraded )
13992  {
13993  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13994  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13995 
13996  (*nchgsides)++;
13997  }
13998  }
13999  }
14000 
14001  /* check for now redundant constraints */
14002  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
14003  {
14004  /* consdata0 became redundant */
14005  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
14006  SCIP_CALL( SCIPdelCons(scip, cons0) );
14007  conss[chkind] = NULL;
14008  if( !consdata0->upgraded )
14009  {
14010  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14011  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
14012 
14013  (*ndelconss)++;
14014  }
14015  continue;
14016  }
14017  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
14018  {
14019  /* consdata1 became redundant */
14020  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14021  SCIP_CALL( SCIPdelCons(scip, cons1) );
14022  conss[c] = NULL;
14023  if( !consdata1->upgraded )
14024  {
14025  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14026  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14027 
14028  (*ndelconss)++;
14029  }
14030  continue;
14031  }
14032 
14033  /* check, if we want to aggregate an (in)equality with an equality:
14034  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14035  */
14036  if( tryaggregation )
14037  {
14038  SCIP_Bool aggregated;
14039 
14040  assert(consdata0->nvars == nvarscommon + nvars0minus1);
14041  assert(consdata1->nvars == nvarscommon + nvars1minus0);
14042 
14043  aggregated = FALSE;
14044  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14045  {
14046  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14047  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14048  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14049  nchgcoefs, &aggregated, cutoff) );
14050 
14051  if( *cutoff )
14052  break;
14053 
14054  /* update array of active constraints */
14055  if( aggregated )
14056  {
14057  assert(!SCIPconsIsActive(cons0));
14058  assert(SCIPconsIsActive(cons1));
14059  conss[chkind] = NULL;
14060  }
14061  }
14062  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14063  {
14064  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14065  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14066  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14067  nchgcoefs, &aggregated, cutoff) );
14068 
14069  if( *cutoff )
14070  break;
14071 
14072  /* update array of active constraints */
14073  if( aggregated )
14074  {
14075  assert(!SCIPconsIsActive(cons1));
14076  assert(SCIPconsIsActive(cons0));
14077  conss[c] = NULL;
14078  }
14079  }
14080  }
14081  }
14082 
14083  /* free temporary memory */
14084  SCIPfreeBufferArray(scip, &diffidx1minus0);
14085  SCIPfreeBufferArray(scip, &diffidx0minus1);
14086  SCIPfreeBufferArray(scip, &commonidx1);
14087  SCIPfreeBufferArray(scip, &commonidx0);
14088 
14089  return SCIP_OKAY;
14090 }
14091 
14092 /** do stuffing presolving on a single constraint */
14093 static
14095  SCIP* scip, /**< SCIP data structure */
14096  SCIP_CONS* cons, /**< linear constraint */
14097  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14098  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14099  * constraints using the cheapest variable? */
14100  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14101  int* nfixedvars, /**< pointer to count the total number of fixed variables */
14102  int* nchgbds /**< pointer to count the total number of tightened bounds */
14103  )
14104 {
14105  SCIP_CONSDATA* consdata;
14106  SCIP_Real* ratios;
14107  int* varpos;
14108  SCIP_Bool* swapped;
14109  SCIP_VAR** vars;
14110  SCIP_Real* vals;
14111  SCIP_VAR* var;
14112  SCIP_Real lb;
14114  SCIP_Real minactivity;
14115  SCIP_Real maxactivity;
14116  SCIP_Real maxcondactivity;
14117  SCIP_Real mincondactivity;
14118  SCIP_Real rhs;
14119  SCIP_Real val;
14120  SCIP_Real obj;
14121  SCIP_Real factor;
14122  SCIP_Bool minactisrelax;
14123  SCIP_Bool maxactisrelax;
14124  SCIP_Bool isminsettoinfinity;
14125  SCIP_Bool ismaxsettoinfinity;
14126  SCIP_Bool tryfixing;
14127  int nsingletons;
14128  int idx;
14129  int v;
14130  int nvars;
14131 
14132  assert(scip != NULL);
14133  assert(cons != NULL);
14134  assert(nfixedvars != NULL);
14135 
14136  consdata = SCIPconsGetData(cons);
14137 
14138  /* we only want to run for inequalities */
14139  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14140  return SCIP_OKAY;
14141 
14142  if( singlevarstuffing )
14143  {
14144  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14145  &isminsettoinfinity, &ismaxsettoinfinity);
14146  }
14147  else
14148  {
14149  minactivity = SCIP_INVALID;
14150  maxactivity = SCIP_INVALID;
14151  isminsettoinfinity = FALSE;
14152  ismaxsettoinfinity = FALSE;
14153  }
14154 
14155  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14156  * the new maxactivity is minus the old minactivity then
14157  */
14158  if( SCIPisInfinity(scip, consdata->rhs) )
14159  {
14160  rhs = -consdata->lhs;
14161  factor = -1.0;
14162  maxactivity = -minactivity;
14163  ismaxsettoinfinity = isminsettoinfinity;
14164  }
14165  else
14166  {
14167  assert(SCIPisInfinity(scip, -consdata->lhs));
14168  rhs = consdata->rhs;
14169  factor = 1.0;
14170  }
14171 
14172  nvars = consdata->nvars;
14173  vars = consdata->vars;
14174  vals = consdata->vals;
14175 
14176  /* check for continuous singletons */
14177  if( singletonstuffing )
14178  {
14179  for( v = 0; v < nvars; ++v )
14180  {
14181  var = vars[v];
14182 
14185  break;
14186  }
14187  }
14188  else
14189  /* we don't want to go into the next block */
14190  v = nvars;
14191 
14192  /* a singleton was found -> perform singleton variable stuffing */
14193  if( v < nvars )
14194  {
14195  assert(singletonstuffing);
14196 
14197  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14198  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14199  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14200 
14201  tryfixing = TRUE;
14202  nsingletons = 0;
14203  mincondactivity = 0.0;
14204  maxcondactivity = 0.0;
14205 
14206  for( v = 0; v < nvars; ++v )
14207  {
14208  var = vars[v];
14209  lb = SCIPvarGetLbGlobal(var);
14210  ub = SCIPvarGetUbGlobal(var);
14211  obj = SCIPvarGetObj(var);
14212  val = factor * vals[v];
14213 
14214  assert(!SCIPisZero(scip, val));
14215 
14216  /* the variable is a singleton and continuous */
14219  {
14220  if( SCIPisNegative(scip, obj) && val > 0 )
14221  {
14222  /* case 1: obj < 0 and coef > 0 */
14223  if( SCIPisInfinity(scip, -lb) )
14224  {
14225  tryfixing = FALSE;
14226  break;
14227  }
14228 
14229  maxcondactivity += val * lb;
14230  mincondactivity += val * lb;
14231  swapped[v] = FALSE;
14232  ratios[nsingletons] = obj / val;
14233  varpos[nsingletons] = v;
14234  nsingletons++;
14235  }
14236  else if( SCIPisPositive(scip, obj) && val < 0 )
14237  {
14238  /* case 2: obj > 0 and coef < 0 */
14239  if( SCIPisInfinity(scip, ub) )
14240  {
14241  tryfixing = FALSE;
14242  break;
14243  }
14244  /* multiply column by (-1) to become case 1.
14245  * now bounds are swapped: ub := -lb, lb := -ub
14246  */
14247 
14248  maxcondactivity += val * ub;
14249  mincondactivity += val * ub;
14250  swapped[v] = TRUE;
14251  ratios[nsingletons] = obj / val;
14252  varpos[nsingletons] = v;
14253  nsingletons++;
14254  }
14255  else if( val > 0 )
14256  {
14257  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14258  * we only consider the lower bound for the constants
14259  */
14260  assert(!SCIPisNegative(scip, obj));
14261 
14262  if( SCIPisInfinity(scip, -lb) )
14263  {
14264  /* maybe unbounded */
14265  tryfixing = FALSE;
14266  break;
14267  }
14268 
14269  maxcondactivity += val * lb;
14270  mincondactivity += val * lb;
14271  }
14272  else
14273  {
14274  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14275  * we only consider the upper bound for the constants
14276  */
14277  assert(!SCIPisPositive(scip, obj));
14278  assert(val < 0);
14279 
14280  if( SCIPisInfinity(scip, ub) )
14281  {
14282  /* maybe unbounded */
14283  tryfixing = FALSE;
14284  break;
14285  }
14286 
14287  maxcondactivity += val * ub;
14288  mincondactivity += val * ub;
14289  }
14290  }
14291  else
14292  {
14293  /* consider contribution of discrete variables, non-singleton
14294  * continuous variables and variables with more than one lock
14295  */
14296  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14297  {
14298  tryfixing = FALSE;
14299  break;
14300  }
14301 
14302  if( val > 0 )
14303  {
14304  maxcondactivity += val * ub;
14305  mincondactivity += val * lb;
14306  }
14307  else
14308  {
14309  maxcondactivity += val * lb;
14310  mincondactivity += val * ub;
14311  }
14312  }
14313  }
14314  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14315  {
14316  SCIP_Real delta;
14317  SCIP_Bool tightened;
14318 #ifdef SCIP_DEBUG
14319  int oldnfixedvars = *nfixedvars;
14320  int oldnchgbds = *nchgbds;
14321 #endif
14322 
14323  SCIPsortRealInt(ratios, varpos, nsingletons);
14324 
14325  /* verify which singleton continuous variables can be fixed */
14326  for( v = 0; v < nsingletons; ++v )
14327  {
14328  idx = varpos[v];
14329  var = vars[idx];
14330  val = factor * vals[idx];
14331  lb = SCIPvarGetLbGlobal(var);
14332  ub = SCIPvarGetUbGlobal(var);
14333 
14334  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14335  assert((val < 0) == swapped[idx]);
14336  val = REALABS(val);
14337 
14338  /* stop fixing if variable bounds are not finite */
14339  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14340  break;
14341 
14344  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14345 
14346  /* calculate the change in the row activities if this variable changes
14347  * its value from its worst to its best bound
14348  */
14349  if( swapped[idx] )
14350  delta = -(lb - ub) * val;
14351  else
14352  delta = (ub - lb) * val;
14353 
14354  assert(!SCIPisNegative(scip, delta));
14355 
14356  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14357  {
14358  if( swapped[idx] )
14359  {
14360  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14361  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14362  }
14363  else
14364  {
14365  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14366  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14367  }
14368 
14369  if( *cutoff )
14370  break;
14371  if( tightened )
14372  {
14373  (*nfixedvars)++;
14374  }
14375  }
14376  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14377  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14378  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14379  * troubles in case of large bounds.
14380  */
14381  else if( SCIPisLE(scip, rhs, mincondactivity) )
14382  {
14383  if( swapped[idx] )
14384  {
14385  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14386  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14387  }
14388  else
14389  {
14390  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14391  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14392  }
14393 
14394  if( *cutoff )
14395  break;
14396  if( tightened )
14397  {
14398  (*nfixedvars)++;
14399  }
14400  }
14401 
14402  maxcondactivity += delta;
14403  mincondactivity += delta;
14404  }
14405 
14406 #ifdef SCIP_DEBUG
14407  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14408  {
14409  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14410  }
14411 #endif
14412  }
14413 
14414  SCIPfreeBufferArray(scip, &swapped);
14415  SCIPfreeBufferArray(scip, &ratios);
14416  SCIPfreeBufferArray(scip, &varpos);
14417  }
14418 
14419  /* perform single-variable stuffing:
14420  * for a linear inequality
14421  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14422  * with a_i > 0 and objective coefficients c_i < 0,
14423  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14424  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14425  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14426  * is redundant.
14427  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14428  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14429  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14430  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14431  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14432  * upper bound.
14433  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14434  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14435  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14436  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14437  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14438  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14439  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14440  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14441  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14442  * c_k * ceil((maxactivity - rhs)/val) is still better than
14443  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14444  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14445  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14446  * sign of coefficients in constraint and objective prevent the use of this method.
14447  */
14448  if( singlevarstuffing && !ismaxsettoinfinity )
14449  {
14450  SCIP_Real bestratio = -SCIPinfinity(scip);
14451  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14452  SCIP_Real ratio;
14453  int bestindex = -1;
14454  int bestuplocks = 0;
14455  int bestdownlocks = 1;
14456  int downlocks;
14457  int uplocks;
14458  SCIPdebug( int oldnfixedvars = *nfixedvars; )
14459  SCIPdebug( int oldnchgbds = *nchgbds; )
14460 
14461  /* loop over all variables to identify the best and second-best ratio */
14462  for( v = 0; v < nvars; ++v )
14463  {
14464  var = vars[v];
14465  obj = SCIPvarGetObj(var);
14466  val = factor * vals[v];
14467 
14468  assert(!SCIPisZero(scip, val));
14469 
14470  ratio = obj / val;
14471 
14472  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14473  if( !SCIPisNegative(scip, ratio) )
14474  {
14475  bestindex = -1;
14476  break;
14477  }
14478 
14479  if( val > 0 )
14480  {
14483  }
14484  else
14485  {
14486  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14488  }
14489 
14490  /* better ratio, update best candidate
14491  * @todo use some tolerance
14492  * @todo check size of domain and updated ratio for integer variables already?
14493  */
14494  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14495  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14496  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14497  {
14498  /* best index becomes second-best*/
14499  if( bestindex != -1 )
14500  {
14501  /* second-best index must not have more than 1 uplock */
14502  if( bestuplocks > 1 )
14503  {
14504  bestindex = -1;
14505  break;
14506  }
14507  else
14508  {
14509  secondbestratio = bestratio;
14510  }
14511  }
14512  bestdownlocks = downlocks;
14513  bestuplocks = uplocks;
14514  bestratio = ratio;
14515  bestindex = v;
14516 
14517  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14518  * if it is not the best, it has too many uplocks -> not applicable
14519  */
14520  if( bestdownlocks > 0 && bestuplocks > 1 )
14521  {
14522  bestindex = -1;
14523  break;
14524  }
14525  }
14526  else
14527  {
14528  /* non-best index must not have more than 1 uplock */
14529  if( uplocks > 1 )
14530  {
14531  bestindex = -1;
14532  break;
14533  }
14534  /* update second-best ratio */
14535  if( ratio > secondbestratio )
14536  {
14537  secondbestratio = ratio;
14538  }
14539  }
14540  }
14541 
14542  /* check if we can apply single variable stuffing */
14543  if( bestindex != -1 && bestdownlocks == 0 )
14544  {
14545  SCIP_Bool tightened = FALSE;
14546  SCIP_Real bounddelta;
14547 
14548  var = vars[bestindex];
14549  obj = SCIPvarGetObj(var);
14550  val = factor * vals[bestindex];
14551  lb = SCIPvarGetLbGlobal(var);
14552  ub = SCIPvarGetUbGlobal(var);
14553  tryfixing = TRUE;
14554 
14555  if( val < 0 )
14556  {
14557  assert(!SCIPisNegative(scip, obj));
14558 
14559  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14560  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14561  {
14562  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14563  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14564  assert(SCIPisPositive(scip, activitydelta));
14565 
14566  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14567 
14568  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14569  assert(SCIPisPositive(scip, bounddelta));
14570  }
14571  else
14572  bounddelta = (maxactivity - rhs)/-val;
14573 
14574  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14575 
14576  if( tryfixing )
14577  {
14578  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14579 
14580  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14581  {
14582  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14583  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14584  }
14585  else
14586  {
14587  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14588  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14589  }
14590  }
14591  }
14592  else
14593  {
14594  assert(!SCIPisPositive(scip, obj));
14595 
14596  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14597  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14598  {
14599  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14600  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14601  assert(SCIPisPositive(scip, activitydelta));
14602 
14603  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14604 
14605  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14606  assert(SCIPisPositive(scip, bounddelta));
14607  }
14608  else
14609  bounddelta = (maxactivity - rhs)/val;
14610 
14611  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14612 
14613  if( tryfixing )
14614  {
14615  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14616 
14617  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14618  {
14619  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14620  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14621  }
14622  else
14623  {
14624  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14625  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14626  }
14627  }
14628  }
14629 
14630  if( *cutoff )
14631  return SCIP_OKAY;
14632  if( tightened )
14633  {
14634  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14635  ++(*nfixedvars);
14636  else
14637  ++(*nchgbds);
14638 
14639  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14640  for( v = 0; v < nvars; ++v )
14641  {
14642  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14643  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14646  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14647  }
14648  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14649 
14650  for( v = 0; v < nvars; ++v )
14651  {
14652  if( v == bestindex )
14653  continue;
14654 
14655  if( factor * vals[v] < 0 )
14656  {
14657  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14658  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14659  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14660  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14661  }
14662  else
14663  {
14664  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14665  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14666  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14667  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14668  }
14669 
14670  if( *cutoff )
14671  return SCIP_OKAY;
14672  if( tightened )
14673  ++(*nfixedvars);
14674  }
14675  SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14676  }
14677  }
14678  }
14679 
14680  return SCIP_OKAY;
14681 }
14682 
14683 /** applies full dual presolving on variables that only appear in linear constraints */
14684 static
14686  SCIP* scip, /**< SCIP data structure */
14687  SCIP_CONS** conss, /**< constraint set */
14688  int nconss, /**< number of constraints */
14689  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14690  int* nchgbds /**< pointer to count the number of bound changes */
14691  )
14692 {
14693  SCIP_Real* redlb;
14694  SCIP_Real* redub;
14695  int* nlocksdown;
14696  int* nlocksup;
14697  SCIP_Bool* isimplint;
14698  SCIP_VAR** origvars;
14699  SCIP_VAR** vars;
14700  SCIP_VAR** conscontvars;
14701  int nvars;
14702  int nbinvars;
14703  int nintvars;
14704  int ncontvars;
14705  int v;
14706  int c;
14707 
14708  /* we calculate redundancy bounds with the following meaning:
14709  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14710  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14711  * then:
14712  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14713  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14714  */
14715 
14716  /* Additionally, we detect continuous variables that are implicitly integral.
14717  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14718  * and all constraints (including the bounds as trivial constraints) in which:
14719  * c_j > 0: the variable is down-locked,
14720  * c_j < 0: the variable is up-locked,
14721  * c_j = 0: the variable appears
14722  * have, apart from j, only integer variables with integral coefficients and integral sides.
14723  * This is because then, the value of the variable is either determined by one of its bounds or
14724  * by one of these constraints, and in all cases, the value of the variable is integral.
14725  */
14726 
14727  assert(scip != NULL);
14728  assert(nconss == 0 || conss != NULL);
14729  assert(nchgbds != NULL);
14730  assert(!SCIPinProbing(scip));
14731 
14732  /* get active variables */
14733  nvars = SCIPgetNVars(scip);
14734  origvars = SCIPgetVars(scip);
14735 
14736  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14737  nbinvars = SCIPgetNBinVars(scip);
14738  if( nbinvars == nvars )
14739  return SCIP_OKAY;
14740 
14741  /* get number of continuous variables */
14742  ncontvars = SCIPgetNContVars(scip);
14743  nintvars = nvars - ncontvars;
14744 
14745  /* copy the variable array since this array might change during the curse of this algorithm */
14746  nvars = nvars - nbinvars;
14747  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14748 
14749  /* allocate temporary memory */
14750  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14751  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14752  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14753  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14754  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14755  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14756 
14757  /* initialize redundancy bounds */
14758  for( v = 0; v < nvars; ++v )
14759  {
14760  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14761  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14762  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14763  }
14764  BMSclearMemoryArray(nlocksdown, nvars);
14765  BMSclearMemoryArray(nlocksup, nvars);
14766 
14767  /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral.
14768  * We better not use SCIPisFeasIntegral() in these checks.
14769  */
14770  for( v = 0; v < ncontvars; v++ )
14771  {
14772  SCIP_VAR* var;
14773  SCIP_Real obj;
14774  SCIP_Real lb;
14775  SCIP_Real ub;
14776 
14777  var = vars[v + nintvars - nbinvars];
14778  lb = SCIPvarGetLbGlobal(var);
14779  ub = SCIPvarGetUbGlobal(var);
14780 
14781  obj = SCIPvarGetObj(var);
14782  if( SCIPisZero(scip, obj) )
14783  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14784  else
14785  {
14786  if( SCIPisPositive(scip, obj) )
14787  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14788  else
14789  {
14790  assert(SCIPisNegative(scip, obj));
14791  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14792  }
14793  }
14794  }
14795 
14796  /* scan all constraints */
14797  for( c = 0; c < nconss; ++c )
14798  {
14799  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14800  * part of checked disjunctions)
14801  */
14802  if( SCIPconsIsLocked(conss[c]) )
14803  {
14804  SCIP_CONSDATA* consdata;
14805  SCIP_Bool lhsexists;
14806  SCIP_Bool rhsexists;
14807  SCIP_Bool hasimpliedpotential;
14808  SCIP_Bool integralcoefs;
14809  int nlockspos;
14810  int contvarpos;
14811  int nconscontvars;
14812  int i;
14813 
14814  consdata = SCIPconsGetData(conss[c]);
14815  assert(consdata != NULL);
14816 
14817  /* get number of times the constraint was locked */
14818  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14819 
14820  /* we do not want to include constraints with locked negation (this would be too weird) */
14821  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14822  {
14823  /* mark all continuous variables as not being implicit integral */
14824  for( i = 0; i < consdata->nvars; ++i )
14825  {
14826  SCIP_VAR* var;
14827 
14828  var = consdata->vars[i];
14830  {
14831  int contv;
14832  contv = SCIPvarGetProbindex(var) - nintvars;
14833  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14834  isimplint[contv] = FALSE;
14835  }
14836  }
14837  continue;
14838  }
14839 
14840  /* check for existing sides */
14841  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14842  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14843 
14844  /* count locks and update redundancy bounds */
14845  contvarpos = -1;
14846  nconscontvars = 0;
14847  hasimpliedpotential = FALSE;
14848  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14849 
14850  for( i = 0; i < consdata->nvars; ++i )
14851  {
14852  SCIP_VAR* var;
14853  SCIP_Real val;
14854  SCIP_Real minresactivity;
14855  SCIP_Real maxresactivity;
14856  SCIP_Real newredlb;
14857  SCIP_Real newredub;
14858  SCIP_Bool minisrelax;
14859  SCIP_Bool maxisrelax;
14860  SCIP_Bool isminsettoinfinity;
14861  SCIP_Bool ismaxsettoinfinity;
14862  int arrayindex;
14863 
14864  var = consdata->vars[i];
14865  val = consdata->vals[i];
14866 
14867  /* check if still all integer variables have integral coefficients */
14868  if( SCIPvarIsIntegral(var) )
14869  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14870 
14871  /* we do not need to process binary variables */
14872  if( SCIPvarIsBinary(var) )
14873  continue;
14874 
14875  if( SCIPconsIsModifiable(conss[c]) )
14876  {
14877  minresactivity = -SCIPinfinity(scip);
14878  maxresactivity = SCIPinfinity(scip);
14879  isminsettoinfinity = TRUE;
14880  ismaxsettoinfinity = TRUE;
14881  }
14882  else
14883  {
14884  /* calculate residual activity bounds if variable would be fixed to zero */
14885  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14886  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14887 
14888  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14889  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14890  * This is needed, because we do not want to rely on relaxed finite resactivities.
14891  */
14892  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14893 
14894  /* check minresactivity for reliability */
14895  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14896  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14897 
14898  /* check maxresactivity for reliability */
14899  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14900  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14901  }
14902 
14903  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14904 
14905  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14906 
14907  newredlb = redlb[arrayindex];
14908  newredub = redub[arrayindex];
14909  if( val > 0.0 )
14910  {
14911  if( lhsexists )
14912  {
14913  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14914  nlocksdown[arrayindex] += nlockspos;
14915  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14916  }
14917  if( rhsexists )
14918  {
14919  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14920  nlocksup[arrayindex] += nlockspos;
14921  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14922  }
14923  }
14924  else
14925  {
14926  if( lhsexists )
14927  {
14928  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14929  nlocksup[arrayindex] += nlockspos;
14930  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14931  }
14932  if( rhsexists )
14933  {
14934  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14935  nlocksdown[arrayindex] += nlockspos;
14936  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14937  }
14938  }
14939 
14940  /* if the variable is integer, we have to round the value to the next integral value */
14941  if( SCIPvarIsIntegral(var) )
14942  {
14943  if( !SCIPisInfinity(scip, newredlb) )
14944  newredlb = SCIPceil(scip, newredlb);
14945  if( !SCIPisInfinity(scip, -newredub) )
14946  newredub = SCIPfloor(scip, newredub);
14947  }
14948 
14949  /* update redundancy bounds */
14950  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14951  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14952 
14953  /* collect the continuous variables of the constraint */
14955  {
14956  int contv;
14957 
14958  assert(nconscontvars < ncontvars);
14959  contvarpos = i;
14960  conscontvars[nconscontvars] = var;
14961  nconscontvars++;
14962 
14963  contv = SCIPvarGetProbindex(var) - nintvars;
14964  assert(0 <= contv && contv < ncontvars);
14965  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14966  }
14967  }
14968 
14969  /* update implicit integer status of continuous variables */
14970  if( hasimpliedpotential )
14971  {
14972  if( nconscontvars > 1 || !integralcoefs )
14973  {
14974  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14975  * none of the continuous variables is implicit integer
14976  */
14977  for( i = 0; i < nconscontvars; i++ )
14978  {
14979  int contv;
14980  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14981  assert(0 <= contv && contv < ncontvars);
14982  isimplint[contv] = FALSE;
14983  }
14984  }
14985  else
14986  {
14987  SCIP_VAR* var;
14988  SCIP_Real val;
14989  SCIP_Real absval;
14990  int contv;
14991 
14992  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14993  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14994  * side(s) of the constraint is integral
14995  */
14996  assert(nconscontvars == 1);
14997  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14998  var = consdata->vars[contvarpos];
14999  val = consdata->vals[contvarpos];
15000  contv = SCIPvarGetProbindex(var) - nintvars;
15001  assert(0 <= contv && contv < ncontvars);
15002  assert(isimplint[contv]);
15003 
15004  absval = REALABS(val);
15005  if( !SCIPisEQ(scip, absval, 1.0) )
15006  isimplint[contv] = FALSE;
15007  else
15008  {
15009  SCIP_Real obj;
15010 
15011  obj = SCIPvarGetObj(var);
15012  if( obj * val >= 0.0 && lhsexists )
15013  {
15014  /* the variable may be blocked by the constraint's left hand side */
15015  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15016  }
15017  if( obj * val <= 0.0 && rhsexists )
15018  {
15019  /* the variable may be blocked by the constraint's left hand side */
15020  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15021  }
15022  }
15023  }
15024  }
15025  }
15026  }
15027 
15028  /* check if any bounds can be tightened due to optimality */
15029  for( v = 0; v < nvars; ++v )
15030  {
15031  SCIP_VAR* var;
15032  SCIP_Real obj;
15033  SCIP_Bool infeasible;
15034  SCIP_Bool tightened;
15035 
15036  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
15037  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15038  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15039 
15040  var = vars[v];
15041  obj = SCIPvarGetObj(var);
15042  if( !SCIPisPositive(scip, -obj) )
15043  {
15044  /* making the variable as small as possible does not increase the objective:
15045  * check if all down locks of the variables are due to linear constraints;
15046  * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make
15047  * constraints redundant is huge, we better do nothing for numerical reasons
15048  */
15049  if( ( SCIPisPositive(scip, obj) || SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) || !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) )
15050  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15051  && !SCIPisHugeValue(scip, -redlb[v])
15052  && redlb[v] < SCIPvarGetUbGlobal(var) )
15053  {
15054  SCIP_Real ub;
15055 
15056  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
15057  * -> tighten upper bound to x_v <= redlb[v]
15058  */
15059  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
15061  redlb[v]);
15062  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
15063  assert(!infeasible);
15064 
15065  ub = SCIPvarGetUbGlobal(var);
15066  redub[v] = MIN(redub[v], ub);
15067  if( tightened )
15068  (*nchgbds)++;
15069  }
15070  }
15071  if( !SCIPisPositive(scip, obj) )
15072  {
15073  /* making the variable as large as possible does not increase the objective:
15074  * check if all up locks of the variables are due to linear constraints;
15075  * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make
15076  * constraints redundant is huge, we better do nothing for numerical reasons
15077  */
15078  if( ( SCIPisPositive(scip, -obj) || SCIPisPositive(scip, -SCIPvarGetLbGlobal(var)) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) )
15079  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15080  && !SCIPisHugeValue(scip, redub[v])
15081  && redub[v] > SCIPvarGetLbGlobal(var) )
15082  {
15083  SCIP_Real lb;
15084 
15085  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15086  * -> tighten lower bound to x_v >= redub[v]
15087  */
15088  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15090  redub[v]);
15091  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15092  assert(!infeasible);
15093 
15094  lb = SCIPvarGetLbGlobal(var);
15095  redlb[v] = MAX(redlb[v], lb);
15096  if( tightened )
15097  (*nchgbds)++;
15098  }
15099  }
15100  }
15101 
15102  /* upgrade continuous variables to implicit integers */
15103  for( v = nintvars - nbinvars; v < nvars; ++v )
15104  {
15105  SCIP_VAR* var;
15106  SCIP_Bool infeasible;
15107 
15108  var = vars[v];
15109  assert(var != NULL);
15110 
15111  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
15112  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15113  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15114  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15115 
15116  /* we can only conclude implicit integrality if the variable appears in no other constraint */
15117  if( isimplint[v - nintvars + nbinvars]
15118  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15119  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15120  {
15121  /* since we locally copied the variable array we can change the variable type immediately */
15122  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15123 
15124  if( infeasible )
15125  {
15126  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15127  *cutoff = TRUE;
15128 
15129  break;
15130  }
15131 
15132  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15134  }
15135  }
15136 
15137  /* free temporary memory */
15138  SCIPfreeBufferArray(scip, &conscontvars);
15139  SCIPfreeBufferArray(scip, &isimplint);
15140  SCIPfreeBufferArray(scip, &nlocksup);
15141  SCIPfreeBufferArray(scip, &nlocksdown);
15142  SCIPfreeBufferArray(scip, &redub);
15143  SCIPfreeBufferArray(scip, &redlb);
15144 
15145  SCIPfreeBufferArray(scip, &vars);
15146 
15147  return SCIP_OKAY;
15148 }
15149 
15150 /** helper function to enforce constraints */
15151 static
15153  SCIP* scip, /**< SCIP data structure */
15154  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15155  SCIP_CONS** conss, /**< constraints to process */
15156  int nconss, /**< number of constraints */
15157  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15158  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15159  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15160  )
15161 {
15162  SCIP_CONSHDLRDATA* conshdlrdata;
15163  SCIP_Bool checkrelmaxabs;
15164  SCIP_Bool violated;
15165  SCIP_Bool cutoff = FALSE;
15166  int c;
15167 
15168  assert(scip != NULL);
15169  assert(conshdlr != NULL);
15170  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15171  assert(result != NULL);
15172 
15173  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15174  assert(conshdlrdata != NULL);
15175 
15176  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15177 
15178  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15179 
15180  /* check for violated constraints
15181  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15182  */
15183  *result = SCIP_FEASIBLE;
15184 
15185  /* check all useful linear constraints for feasibility */
15186  for( c = 0; c < nusefulconss; ++c )
15187  {
15188  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15189 
15190  if( violated )
15191  {
15192  /* insert LP row as cut */
15193  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15194  if ( cutoff )
15195  *result = SCIP_CUTOFF;
15196  else
15197  *result = SCIP_SEPARATED;
15198  }
15199  }
15200 
15201  /* check all obsolete linear constraints for feasibility */
15202  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15203  {
15204  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15205 
15206  if( violated )
15207  {
15208  /* insert LP row as cut */
15209  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15210  if ( cutoff )
15211  *result = SCIP_CUTOFF;
15212  else
15213  *result = SCIP_SEPARATED;
15214  }
15215  }
15216 
15217  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15218 
15219  return SCIP_OKAY;
15220 }
15221 
15222 /*
15223  * Callback methods of constraint handler
15224  */
15225 
15226 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15227 static
15228 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15229 { /*lint --e{715}*/
15230  assert(scip != NULL);
15231  assert(conshdlr != NULL);
15232  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15233 
15234  /* call inclusion method of constraint handler */
15236 
15237  *valid = TRUE;
15238 
15239  return SCIP_OKAY;
15240 }
15241 
15242 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15243 static
15244 SCIP_DECL_CONSFREE(consFreeLinear)
15245 { /*lint --e{715}*/
15246  SCIP_CONSHDLRDATA* conshdlrdata;
15248  assert(scip != NULL);
15249  assert(conshdlr != NULL);
15250  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15251 
15252  /* free constraint handler data */
15253  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15254  assert(conshdlrdata != NULL);
15255 
15256  conshdlrdataFree(scip, &conshdlrdata);
15257 
15258  SCIPconshdlrSetData(conshdlr, NULL);
15259 
15260  return SCIP_OKAY;
15261 }
15262 
15264 /** initialization method of constraint handler (called after problem was transformed) */
15265 static
15266 SCIP_DECL_CONSINIT(consInitLinear)
15267 {
15268  SCIP_CONSHDLRDATA* conshdlrdata;
15269  int c;
15270 
15271  assert(scip != NULL);
15272 
15273  /* check for event handler */
15274  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15275  assert(conshdlrdata != NULL);
15276  assert(conshdlrdata->eventhdlr != NULL);
15277  assert(nconss == 0 || conss != NULL);
15278 
15279  conshdlrdata->naddconss = 0;
15280 
15281  /* catch events for the constraints */
15282  for( c = 0; c < nconss; ++c )
15283  {
15284  /* catch all events */
15285  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15286  }
15287 
15288  return SCIP_OKAY;
15289 }
15290 
15291 
15292 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15293 static
15294 SCIP_DECL_CONSEXIT(consExitLinear)
15295 {
15296  SCIP_CONSHDLRDATA* conshdlrdata;
15297  int c;
15298 
15299  assert(scip != NULL);
15300 
15301  /* check for event handler */
15302  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15303  assert(conshdlrdata != NULL);
15304  assert(conshdlrdata->eventhdlr != NULL);
15305 
15306  /* drop events for the constraints */
15307  for( c = nconss - 1; c >= 0; --c )
15308  {
15309  SCIP_CONSDATA* consdata;
15310 
15311  consdata = SCIPconsGetData(conss[c]);
15312  assert(consdata != NULL);
15314  if( consdata->eventdata != NULL )
15315  {
15316  /* drop all events */
15317  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15318  assert(consdata->eventdata == NULL);
15319  }
15320  }
15321 
15322  return SCIP_OKAY;
15323 }
15324 
15325 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15326 static
15328  SCIP* scip, /**< SCIP data structure */
15329  SCIP_Real lhs, /**< left hand side */
15330  SCIP_Real rhs /**< right hand side */
15331  )
15332 {
15333  assert(scip != NULL);
15334 
15335  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15336 }
15337 
15338 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15339 static
15341  SCIP* scip, /**< SCIP data structure */
15342  SCIP_Real x /**< value */
15343  )
15344 {
15345  assert(scip != NULL);
15347  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15348 }
15349 
15350 /** performs linear constraint type classification as used for MIPLIB
15351  *
15352  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15353  *
15354  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15355  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15356  * Similarly, if specialized constraints were created through the API, these are currently not present.
15357  */
15359  SCIP* scip, /**< SCIP data structure */
15360  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15361  )
15362 {
15363  int c;
15364  SCIP_CONSHDLR* conshdlr;
15365  SCIP_CONS** conss;
15366  int nconss;
15367 
15368  assert(scip != NULL);
15369  assert(linconsstats != NULL);
15370  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15371  assert(conshdlr != NULL);
15372 
15373  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15374  {
15375  conss = SCIPgetConss(scip);
15376  nconss = SCIPgetNConss(scip);
15377  }
15378  else
15379  {
15380  conss = SCIPconshdlrGetConss(conshdlr);
15381  nconss = SCIPconshdlrGetNConss(conshdlr);
15382  }
15383 
15384  /* reset linear constraint type classification */
15385  SCIPlinConsStatsReset(linconsstats);
15386 
15387  /* loop through all constraints */
15388  for( c = 0; c < nconss; c++ )
15389  {
15390  SCIP_CONS* cons;
15391  SCIP_CONSDATA* consdata;
15392  SCIP_Real lhs;
15393  SCIP_Real rhs;
15394  int i;
15395 
15396  /* get constraint */
15397  cons = conss[c];
15398  assert(cons != NULL);
15399 
15400  /* skip constraints that are not handled by the constraint handler */
15401  if( SCIPconsGetHdlr(cons) != conshdlr )
15402  continue;
15403 
15404  /* get constraint data */
15405  consdata = SCIPconsGetData(cons);
15406  assert(consdata != NULL);
15407  rhs = consdata->rhs;
15408  lhs = consdata->lhs;
15409 
15410  /* merge multiples and delete variables with zero coefficient */
15411  SCIP_CALL( mergeMultiples(scip, cons) );
15412  for( i = 0; i < consdata->nvars; i++ )
15413  {
15414  assert(!SCIPisZero(scip, consdata->vals[i]));
15415  }
15416 
15417  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15418  if( consdata->nvars == 0 )
15419  {
15420  SCIPdebugMsg(scip, "classified as EMPTY: ");
15421  SCIPdebugPrintCons(scip, cons, NULL);
15423 
15424  continue;
15425  }
15426 
15427  /* is constraint of type SCIP_CONSTYPE_FREE? */
15428  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15429  {
15430  SCIPdebugMsg(scip, "classified as FREE: ");
15431  SCIPdebugPrintCons(scip, cons, NULL);
15433 
15434  continue;
15435  }
15436 
15437  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15438  if( consdata->nvars == 1 )
15439  {
15440  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15441  SCIPdebugPrintCons(scip, cons, NULL);
15442  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15443 
15444  continue;
15445  }
15446 
15447  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15448  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15449  {
15450  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15451  SCIPdebugPrintCons(scip, cons, NULL);
15453 
15454  continue;
15455  }
15456 
15457  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15458  if( consdata->nvars == 2 )
15459  {
15460  SCIP_LINCONSTYPE constype;
15461 
15462  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15463  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15464  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15465  {
15466  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15467  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15468  }
15469  else
15470  {
15471  constype = SCIP_LINCONSTYPE_VARBOUND;
15472  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15473  }
15474  SCIPdebugPrintCons(scip, cons, NULL);
15475 
15476  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15477 
15478  continue;
15479  }
15480 
15481  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15482  {
15483  SCIP_Real scale;
15484  SCIP_Real b;
15485  SCIP_Bool unmatched;
15486  int nnegbinvars;
15487 
15488  unmatched = FALSE;
15489  nnegbinvars = 0;
15490 
15491  scale = REALABS(consdata->vals[0]);
15492 
15493  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15494  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15495  {
15496  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15497  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15498  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15499  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15500 
15501  if( consdata->vals[i] < 0.0 )
15502  nnegbinvars++;
15503  }
15504 
15505  if( !unmatched )
15506  {
15507  if( SCIPisEQ(scip, lhs, rhs) )
15508  {
15509  b = rhs/scale + nnegbinvars;
15510  if( SCIPisEQ(scip, 1.0, b) )
15511  {
15512  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15513  SCIPdebugPrintCons(scip, cons, NULL);
15515 
15516  continue;
15517  }
15518  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15519  {
15520  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15521  SCIPdebugPrintCons(scip, cons, NULL);
15523 
15524  continue;
15525  }
15526  }
15527 
15528  /* compute right hand side divided by scale */
15529  if( !SCIPisInfinity(scip, rhs) )
15530  b = rhs/scale + nnegbinvars;
15531  else
15532  b = SCIPinfinity(scip);
15533 
15534  if( SCIPisEQ(scip, 1.0, b) )
15535  {
15536  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15537  SCIPdebugPrintCons(scip, cons, NULL);
15539 
15540  /* relax right hand side to prevent further classifications */
15541  rhs = SCIPinfinity(scip);
15542  }
15543  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15544  {
15545  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15546  SCIPdebugPrintCons(scip, cons, NULL);
15547 
15549 
15550  /* relax right hand side to prevent further classifications */
15551  rhs = SCIPinfinity(scip);
15552  }
15553 
15554  if( !SCIPisInfinity(scip, lhs) )
15555  b = lhs/scale + nnegbinvars;
15556  else
15557  b = SCIPinfinity(scip);
15558 
15559  if( SCIPisEQ(scip, 1.0, b) )
15560  {
15561  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15562  SCIPdebugPrintCons(scip, cons, NULL);
15564 
15565  /* relax left hand side to prevent further classifications */
15566  lhs = -SCIPinfinity(scip);
15567  }
15568 
15569  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15570  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15571  continue;
15572  }
15573  }
15574 
15575  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15576  /* @todo If coefficients or rhs are not integral, we currently do not check
15577  * if the constraint could be scaled (finitely), such that they are.
15578  */
15579  {
15580  SCIP_Real b;
15581  SCIP_Bool unmatched;
15582 
15583  b = rhs;
15584  unmatched = FALSE;
15585  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15586  {
15587  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15588  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15589  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15590  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15591 
15592  if( SCIPisNegative(scip, consdata->vals[i]) )
15593  b -= consdata->vals[i];
15594  }
15595  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15596 
15597  if( !unmatched )
15598  {
15599  if( SCIPisEQ(scip, lhs, rhs) )
15600  {
15601  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15602  SCIPdebugPrintCons(scip, cons, NULL);
15603 
15605 
15606  continue;
15607  }
15608  else
15609  {
15610  SCIP_Bool matched;
15611 
15612  matched = FALSE;
15613  for( i = 0; i < consdata->nvars && !matched; i++ )
15614  {
15615  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15616  }
15617 
15618  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15619  SCIPdebugPrintCons(scip, cons, NULL);
15621  }
15622 
15623  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15624  if( SCIPisInfinity(scip, -lhs) )
15625  continue;
15626  else
15627  rhs = SCIPinfinity(scip);
15628  }
15629  }
15630 
15631  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15632  {
15633  SCIP_Real b;
15634  SCIP_Bool unmatched;
15635 
15636  unmatched = FALSE;
15637 
15638  b = rhs;
15639  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15640 
15641  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15642  {
15643  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15644  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15645  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15646  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15647  }
15648 
15649  if( !unmatched )
15650  {
15651  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15652  SCIPdebugPrintCons(scip, cons, NULL);
15654 
15655  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15656  if( SCIPisInfinity(scip, -lhs) )
15657  continue;
15658  else
15659  rhs = SCIPinfinity(scip);
15660  }
15661  }
15662 
15663  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15664  {
15665  SCIP_Bool unmatched;
15666 
15667  unmatched = FALSE;
15668  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15669  {
15670  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15671  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15672  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15673  unmatched = TRUE;
15674  }
15675 
15676  if( !unmatched )
15677  {
15678  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15679  SCIPdebugPrintCons(scip, cons, NULL);
15680  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15681 
15682  continue;
15683  }
15684  }
15685 
15686  /* no special structure detected */
15687  SCIPdebugMsg(scip, "classified as GENERAL: ");
15688  SCIPdebugPrintCons(scip, cons, NULL);
15689  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15690  }
15691 
15692  return SCIP_OKAY;
15693 }
15694 
15695 
15696 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15697 static
15698 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15699 { /*lint --e{715}*/
15700  int c;
15701 #ifdef SCIP_STATISTIC
15702  SCIP_CONSHDLRDATA* conshdlrdata;
15703  int ngoodconss;
15704  int nallconss;
15705 #endif
15706 
15707  /* delete all linear constraints that were upgraded to a more specific constraint type;
15708  * make sure, only active variables remain in the remaining constraints
15709  */
15710  assert(scip != NULL);
15711 
15712 #ifdef SCIP_STATISTIC
15713  /* count number of well behaved linear constraints */
15714  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15715  assert(conshdlrdata != NULL);
15716 
15717  ngoodconss = 0;
15718  nallconss = 0;
15719 
15720  for( c = 0; c < nconss; ++c )
15721  {
15722  SCIP_CONSDATA* consdata;
15723 
15724  if( SCIPconsIsDeleted(conss[c]) )
15725  continue;
15726 
15727  consdata = SCIPconsGetData(conss[c]);
15728  assert(consdata != NULL);
15729 
15730  if( consdata->upgraded )
15731  continue;
15732 
15733  nallconss++;
15734 
15735  consdataRecomputeMaxActivityDelta(scip, consdata);
15736 
15737  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15738  ngoodconss++;
15739  }
15740  if( nallconss )
15741  {
15742  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15743  }
15744 #endif
15745 
15746  for( c = 0; c < nconss; ++c )
15747  {
15748  SCIP_CONSDATA* consdata;
15749 
15750  if( SCIPconsIsDeleted(conss[c]) )
15751  continue;
15752 
15753  consdata = SCIPconsGetData(conss[c]);
15754  assert(consdata != NULL);
15755 
15756  if( consdata->upgraded )
15757  {
15758  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15759  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15760  */
15761  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15762  }
15763  else
15764  {
15765  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15766  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15767  }
15768  }
15769 
15770  return SCIP_OKAY;
15771 }
15772 
15773 /** solving process initialization method of constraint handler */
15774 static
15775 SCIP_DECL_CONSINITSOL(consInitsolLinear)
15776 { /*lint --e{715}*/
15777  /* add nlrow representation to NLP, if NLP had been constructed */
15778  if( SCIPisNLPConstructed(scip) )
15779  {
15780  int c;
15781  for( c = 0; c < nconss; ++c )
15782  {
15783  SCIP_CALL( addNlrow(scip, conss[c]) );
15784  }
15785  }
15786 
15787  return SCIP_OKAY;
15788 }
15789 
15790 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15791 static
15792 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15793 { /*lint --e{715}*/
15794  int c;
15795 
15796  assert(scip != NULL);
15797 
15798  /* release the rows and nlrows of all constraints */
15799  for( c = 0; c < nconss; ++c )
15800  {
15801  SCIP_CONSDATA* consdata;
15802 
15803  consdata = SCIPconsGetData(conss[c]);
15804  assert(consdata != NULL);
15805 
15806  if( consdata->row != NULL )
15807  {
15808  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15809  }
15810 
15811  if( consdata->nlrow != NULL )
15812  {
15813  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15814  }
15815  }
15816 
15817  /* if this is a restart, convert cutpool rows into linear constraints */
15818  if( restart )
15819  {
15820  int ncutsadded;
15821 
15822  ncutsadded = 0;
15823 
15824  /* create out of all active cuts in cutpool linear constraints */
15825  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15826 
15827  if( ncutsadded > 0 )
15828  {
15830  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15831  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15832  * line correctly
15833  */
15835  }
15836  }
15837 
15838  return SCIP_OKAY;
15839 }
15840 
15841 
15842 /** constraint activation notification method of constraint handler */
15843 static
15844 SCIP_DECL_CONSACTIVE(consActiveLinear)
15845 { /*lint --e{715}*/
15846  assert(cons != NULL);
15847 
15848  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
15849  {
15850  SCIP_CALL( addNlrow(scip, cons) );
15851  }
15852 
15853  return SCIP_OKAY;
15854 }
15855 
15856 /** constraint deactivation notification method of constraint handler */
15857 static
15858 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15859 { /*lint --e{715}*/
15860  SCIP_CONSDATA* consdata;
15861 
15862  assert(scip != NULL);
15863  assert(conshdlr != NULL);
15864  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15865  assert(cons != NULL );
15866 
15867  /* get constraint data */
15868  consdata = SCIPconsGetData(cons);
15869  assert(consdata != NULL);
15870 
15871  if( SCIPconsIsDeleted(cons) )
15872  {
15873  SCIP_CONSHDLRDATA* conshdlrdata;
15874 
15875  /* check for event handler */
15876  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15877  assert(conshdlrdata != NULL);
15878  assert(conshdlrdata->eventhdlr != NULL);
15879 
15880  /* free event data */
15881  if( consdata->eventdata != NULL )
15882  {
15883  /* drop bound change events of variables */
15884  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15885  }
15886  assert(consdata->eventdata == NULL);
15887  }
15888 
15889  /* remove row from NLP, if still in solving
15890  * if we are in exitsolve, the whole NLP will be freed anyway
15891  */
15892  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15893  {
15894  SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15895  }
15896 
15897  return SCIP_OKAY;
15898 }
15899 
15900 
15901 /** frees specific constraint data */
15902 static
15903 SCIP_DECL_CONSDELETE(consDeleteLinear)
15904 { /*lint --e{715}*/
15905  assert(scip != NULL);
15906  assert(conshdlr != NULL);
15907  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15908 
15909  if( (*consdata)->eventdata != NULL )
15910  {
15911  SCIP_CONSHDLRDATA* conshdlrdata;
15912 
15913  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15914  assert(conshdlrdata != NULL);
15915 
15916  /* drop all events */
15917  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15918  assert((*consdata)->eventdata == NULL);
15919  }
15920 
15921  /* free linear constraint */
15922  SCIP_CALL( consdataFree(scip, consdata) );
15923 
15924  return SCIP_OKAY;
15925 }
15926 
15927 
15928 /** transforms constraint data into data belonging to the transformed problem */
15929 static
15930 SCIP_DECL_CONSTRANS(consTransLinear)
15931 { /*lint --e{715}*/
15932  SCIP_CONSDATA* sourcedata;
15933  SCIP_CONSDATA* targetdata;
15934 
15935  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15936 
15937  assert(scip != NULL);
15938  assert(conshdlr != NULL);
15939  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15940  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15941  assert(sourcecons != NULL);
15942  assert(targetcons != NULL);
15943 
15944  sourcedata = SCIPconsGetData(sourcecons);
15945  assert(sourcedata != NULL);
15946  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15947 
15948  /* create linear constraint data for target constraint */
15949  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15950 
15951 #ifndef NDEBUG
15952  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15953  if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15954  {
15955  int n;
15956  for(n = targetdata->nvars - 1; n >= 0; --n )
15957  assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15958  }
15959 #endif
15960 
15961  /* create target constraint */
15962  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15963  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15964  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15965  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15966  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15967 
15968  return SCIP_OKAY;
15969 }
15970 
15971 
15972 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15973 static
15974 SCIP_DECL_CONSINITLP(consInitlpLinear)
15975 { /*lint --e{715}*/
15976  int c;
15977 
15978  assert(scip != NULL);
15979  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15980 
15981  *infeasible = FALSE;
15982 
15983  for( c = 0; c < nconss && !(*infeasible); ++c )
15984  {
15985  assert(SCIPconsIsInitial(conss[c]));
15986  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15987  }
15988 
15989  return SCIP_OKAY;
15990 }
15991 
15992 
15993 /** separation method of constraint handler for LP solutions */
15994 static
15995 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15996 { /*lint --e{715}*/
15997  SCIP_CONSHDLRDATA* conshdlrdata;
15998  SCIP_Real loclowerbound;
15999  SCIP_Real glblowerbound;
16000  SCIP_Real cutoffbound;
16001  SCIP_Real maxbound;
16002  SCIP_Bool separatecards;
16003  SCIP_Bool cutoff;
16004  int c;
16005  int depth;
16006  int nrounds;
16007  int maxsepacuts;
16008  int ncuts;
16009 
16010  assert(scip != NULL);
16011  assert(conshdlr != NULL);
16012  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16013  assert(result != NULL);
16015  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16016  assert(conshdlrdata != NULL);
16017  depth = SCIPgetDepth(scip);
16018  nrounds = SCIPgetNSepaRounds(scip);
16019 
16020  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16021 
16022  *result = SCIP_DIDNOTRUN;
16023 
16024  /* only call the separator a given number of times at each node */
16025  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16026  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16027  return SCIP_OKAY;
16028 
16029  /* get the maximal number of cuts allowed in a separation round */
16030  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16031 
16032  /* check if we want to produce knapsack cardinality cuts at this node */
16033  loclowerbound = SCIPgetLocalLowerbound(scip);
16034  glblowerbound = SCIPgetLowerbound(scip);
16035  cutoffbound = SCIPgetCutoffbound(scip);
16036  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16037  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16038  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16039 
16040  *result = SCIP_DIDNOTFIND;
16041  ncuts = 0;
16042  cutoff = FALSE;
16043 
16044  /* check all useful linear constraints for feasibility */
16045  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16046  {
16047  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16048  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16049  }
16050 
16051  /* adjust return value */
16052  if( cutoff )
16053  *result = SCIP_CUTOFF;
16054  else if( ncuts > 0 )
16055  *result = SCIP_SEPARATED;
16056 
16057  /* combine linear constraints to get more cuts */
16058  /**@todo further cuts of linear constraints */
16059 
16060  return SCIP_OKAY;
16061 }
16062 
16063 
16064 /** separation method of constraint handler for arbitrary primal solutions */
16065 static
16066 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16067 { /*lint --e{715}*/
16068  SCIP_CONSHDLRDATA* conshdlrdata;
16069  int c;
16070  int depth;
16071  int nrounds;
16072  int maxsepacuts;
16073  int ncuts;
16074  SCIP_Bool cutoff;
16075 
16076  assert(scip != NULL);
16077  assert(conshdlr != NULL);
16078  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16079  assert(result != NULL);
16080 
16081  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16082  assert(conshdlrdata != NULL);
16083  depth = SCIPgetDepth(scip);
16084  nrounds = SCIPgetNSepaRounds(scip);
16086  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16087 
16088  *result = SCIP_DIDNOTRUN;
16089 
16090  /* only call the separator a given number of times at each node */
16091  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16092  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16093  return SCIP_OKAY;
16094 
16095  /* get the maximal number of cuts allowed in a separation round */
16096  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16097 
16098  *result = SCIP_DIDNOTFIND;
16099  ncuts = 0;
16100  cutoff = FALSE;
16101 
16102  /* check all useful linear constraints for feasibility */
16103  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16104  {
16105  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16106  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16107  }
16108 
16109  /* adjust return value */
16110  if( cutoff )
16111  *result = SCIP_CUTOFF;
16112  else if( ncuts > 0 )
16113  *result = SCIP_SEPARATED;
16114 
16115  /* combine linear constraints to get more cuts */
16116  /**@todo further cuts of linear constraints */
16117 
16118  return SCIP_OKAY;
16119 }
16120 
16121 
16122 /** constraint enforcing method of constraint handler for LP solutions */
16123 static
16124 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16125 { /*lint --e{715}*/
16126  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16127 
16128  return SCIP_OKAY;
16129 }
16130 
16131 /** constraint enforcing method of constraint handler for relaxation solutions */
16132 static
16133 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16134 { /*lint --e{715}*/
16135  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16136 
16137  return SCIP_OKAY;
16138 }
16139 
16140 /** constraint enforcing method of constraint handler for pseudo solutions */
16141 static
16142 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16143 { /*lint --e{715}*/
16144  SCIP_CONSHDLRDATA* conshdlrdata;
16145  SCIP_Bool checkrelmaxabs;
16146  SCIP_Bool violated;
16147  int c;
16148 
16149  assert(scip != NULL);
16150  assert(conshdlr != NULL);
16151  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16152  assert(result != NULL);
16153 
16154  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16155  assert(conshdlrdata != NULL);
16156 
16157  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16158 
16159  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16160 
16161  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16162  if( objinfeasible )
16163  {
16164  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16165 
16166  *result = SCIP_DIDNOTRUN;
16167  return SCIP_OKAY;
16168  }
16169 
16170  /* check all linear constraints for feasibility */
16171  violated = FALSE;
16172  for( c = 0; c < nconss && !violated; ++c )
16173  {
16174  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16175  }
16176 
16177  if( violated )
16178  *result = SCIP_INFEASIBLE;
16179  else
16180  *result = SCIP_FEASIBLE;
16181 
16182  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16183 
16184  return SCIP_OKAY;
16185 }
16186 
16187 
16188 /** feasibility check method of constraint handler for integral solutions */
16189 static
16190 SCIP_DECL_CONSCHECK(consCheckLinear)
16191 { /*lint --e{715}*/
16192  SCIP_CONSHDLRDATA* conshdlrdata;
16193  SCIP_Bool checkrelmaxabs;
16194  int c;
16195 
16196  assert(scip != NULL);
16197  assert(conshdlr != NULL);
16198  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16199  assert(result != NULL);
16200 
16201  *result = SCIP_FEASIBLE;
16202 
16203  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16204  assert(conshdlrdata != NULL);
16205 
16206  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16207 
16208  /*debugMsg(scip, "Check method of linear constraints\n");*/
16210  /* check all linear constraints for feasibility */
16211  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16212  {
16213  SCIP_Bool violated = FALSE;
16214  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16215 
16216  if( violated )
16217  {
16218  *result = SCIP_INFEASIBLE;
16219 
16220  if( printreason )
16221  {
16222  SCIP_CONSDATA* consdata;
16223  SCIP_Real activity;
16224 
16225  consdata = SCIPconsGetData(conss[c]);
16226  assert( consdata != NULL);
16227 
16228  activity = consdataGetActivity(scip, consdata, sol);
16229 
16230  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16231  SCIPinfoMessage(scip, NULL, ";\n");
16232 
16233  if( activity == SCIP_INVALID ) /*lint !e777*/
16234  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16235  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16236  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16237  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16238  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16239  }
16240  }
16241  }
16242 
16243  return SCIP_OKAY;
16244 }
16245 
16246 
16247 /** domain propagation method of constraint handler */
16248 static
16249 SCIP_DECL_CONSPROP(consPropLinear)
16250 { /*lint --e{715}*/
16251  SCIP_CONSHDLRDATA* conshdlrdata;
16252  SCIP_Bool rangedrowpropagation = FALSE;
16253  SCIP_Bool tightenbounds;
16254  SCIP_Bool cutoff;
16255 
16256  int nchgbds;
16257  int i;
16258 
16259  assert(scip != NULL);
16260  assert(conshdlr != NULL);
16261  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16262  assert(result != NULL);
16263 
16264  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16265  assert(conshdlrdata != NULL);
16266 
16267  /*debugMsg(scip, "Prop method of linear constraints\n");*/
16269  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16270  if( SCIPinProbing(scip) )
16271  tightenbounds = TRUE;
16272  else
16273  {
16274  int depth;
16275  int propfreq;
16276  int tightenboundsfreq;
16277  int rangedrowfreq;
16278 
16279  depth = SCIPgetDepth(scip);
16280  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16281  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16282  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16283  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16284 
16285  /* check if we want to do ranged row propagation */
16286  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16287  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16288  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16289  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16290  rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16291  && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16292  }
16293 
16294  cutoff = FALSE;
16295  nchgbds = 0;
16296 
16297  /* process constraints marked for propagation */
16298  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16299  {
16300  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16301  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16302  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16303  }
16304 
16305  /* adjust result code */
16306  if( cutoff )
16307  *result = SCIP_CUTOFF;
16308  else if( nchgbds > 0 )
16309  *result = SCIP_REDUCEDDOM;
16310  else
16311  *result = SCIP_DIDNOTFIND;
16312 
16313  return SCIP_OKAY;
16314 }
16315 
16316 
16317 #define MAXCONSPRESOLROUNDS 10
16318 /** presolving method of constraint handler */
16319 static
16320 SCIP_DECL_CONSPRESOL(consPresolLinear)
16321 { /*lint --e{715}*/
16322  SCIP_CONSHDLRDATA* conshdlrdata;
16323  SCIP_CONS* cons;
16324  SCIP_CONSDATA* consdata;
16325  SCIP_Real minactivity;
16326  SCIP_Real maxactivity;
16327  SCIP_Bool minactisrelax;
16328  SCIP_Bool maxactisrelax;
16329  SCIP_Bool isminsettoinfinity;
16330  SCIP_Bool ismaxsettoinfinity;
16331  SCIP_Bool cutoff;
16332  int oldnfixedvars;
16333  int oldnaggrvars;
16334  int oldnchgbds;
16335  int oldndelconss;
16336  int oldnupgdconss;
16337  int oldnchgcoefs;
16338  int oldnchgsides;
16339  int firstchange;
16340  int firstupgradetry;
16341  int c;
16342 
16343  assert(scip != NULL);
16344  assert(conshdlr != NULL);
16345  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16346  assert(result != NULL);
16347 
16348  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16349 
16350  /* remember old preprocessing counters */
16351  cutoff = FALSE;
16352  oldnfixedvars = *nfixedvars;
16353  oldnaggrvars = *naggrvars;
16354  oldnchgbds = *nchgbds;
16355  oldndelconss = *ndelconss;
16356  oldnupgdconss = *nupgdconss;
16357  oldnchgcoefs = *nchgcoefs;
16358  oldnchgsides = *nchgsides;
16359 
16360  /* get constraint handler data */
16361  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16362  assert(conshdlrdata != NULL);
16363 
16364  /* process single constraints */
16365  firstchange = INT_MAX;
16366  firstupgradetry = INT_MAX;
16367  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16368  {
16369  int npresolrounds;
16370  SCIP_Bool infeasible;
16371 
16372  infeasible = FALSE;
16373 
16374  cons = conss[c];
16375  assert(SCIPconsIsActive(cons));
16376  consdata = SCIPconsGetData(cons);
16377  assert(consdata != NULL);
16378 
16379  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16380  if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16381  {
16382  consdata->lhs = consdata->rhs;
16383  assert(consdata->row == NULL);
16384  }
16385 
16386  if( consdata->eventdata == NULL )
16387  {
16388  /* catch bound change events of variables */
16389  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16390  assert(consdata->eventdata != NULL);
16391  }
16392 
16393  /* constraint should not be already presolved in the initial round */
16394  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16395  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16396  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16397  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16398 
16399  /* incorporate fixings and aggregations in constraint */
16400  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16401 
16402  if( infeasible )
16403  {
16404  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16405  cutoff = TRUE;
16406  break;
16407  }
16408 
16409  assert(consdata->removedfixings);
16410 
16411  /* we can only presolve linear constraints, that are not modifiable */
16412  if( SCIPconsIsModifiable(cons) )
16413  continue;
16414 
16415  /* remember the first changed constraint to begin the next aggregation round with */
16416  if( firstchange == INT_MAX && consdata->changed )
16417  firstchange = c;
16418 
16419  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16420  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16421  firstupgradetry = c;
16422 
16423  /* check, if constraint is already preprocessed */
16424  if( consdata->presolved )
16425  continue;
16426 
16427  assert(SCIPconsIsActive(cons));
16428 
16429  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16430  SCIPdebugPrintCons(scip, cons, NULL);
16431 
16432  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16433  * to avoid nearly infinite cycling due to very small bound changes)
16434  */
16435  npresolrounds = 0;
16436  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16437  {
16438  assert(!cutoff);
16439  npresolrounds++;
16440 
16441  /* mark constraint being presolved and propagated */
16442  consdata->presolved = TRUE;
16443  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16444 
16445  /* normalize constraint */
16446  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16447 
16448  if( infeasible )
16449  {
16450  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16451  cutoff = TRUE;
16452  break;
16453  }
16454 
16455  /* tighten left and right hand side due to integrality */
16456  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16457 
16458  if( infeasible )
16459  {
16460  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16461  cutoff = TRUE;
16462  break;
16463  }
16464 
16465  /* check bounds */
16466  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16467  {
16468  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16469  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16470  cutoff = TRUE;
16471  break;
16472  }
16473 
16474  /* tighten variable's bounds */
16475  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16476  if( cutoff )
16477  break;
16478 
16479  /* check for fixed variables */
16480  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16481  if( cutoff )
16482  break;
16483 
16484  /* check constraint for infeasibility and redundancy */
16485  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16486  &isminsettoinfinity, &ismaxsettoinfinity);
16487  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16488  {
16489  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16490  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16491  cutoff = TRUE;
16492  break;
16493  }
16494  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16495  {
16496  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16497  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16498  SCIP_CALL( SCIPdelCons(scip, cons) );
16499  assert(!SCIPconsIsActive(cons));
16500 
16501  if( !consdata->upgraded )
16502  (*ndelconss)++;
16503  break;
16504  }
16505  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16506  {
16507  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16508  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16509  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16510  if( !consdata->upgraded )
16511  (*nchgsides)++;
16512  }
16513  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16514  {
16515  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16516  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16517  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16518  if( !consdata->upgraded )
16519  (*nchgsides)++;
16520  }
16521 
16522  /* handle empty constraint */
16523  if( consdata->nvars == 0 )
16524  {
16525  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16526  {
16527  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16528  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16529  cutoff = TRUE;
16530  }
16531  else
16532  {
16533  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16534  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16535  SCIP_CALL( SCIPdelCons(scip, cons) );
16536  assert(!SCIPconsIsActive(cons));
16537 
16538  if( !consdata->upgraded )
16539  (*ndelconss)++;
16540  }
16541  break;
16542  }
16543 
16544  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16545  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16546 
16547  /* try to simplify inequalities */
16548  if( conshdlrdata->simplifyinequalities )
16549  {
16550  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16551 
16552  if( cutoff )
16553  break;
16554  }
16555 
16556  /* aggregation variable in equations */
16557  if( conshdlrdata->aggregatevariables )
16558  {
16559  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16560  if( cutoff )
16561  break;
16562  }
16563  }
16564 
16565  if( !cutoff && !SCIPisStopped(scip) )
16566  {
16567  /* perform ranged row propagation */
16568  if( conshdlrdata->rangedrowpropagation )
16569  {
16570  int lastnfixedvars;
16571 
16572  lastnfixedvars = *nfixedvars;
16573 
16574  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16575  if( !cutoff )
16576  {
16577  if( lastnfixedvars < *nfixedvars )
16578  {
16579  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16580  }
16581  }
16582  }
16583 
16584  /* extract cliques from constraint */
16585  if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16586  {
16587  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16588  nfixedvars, nchgbds, &cutoff) );
16589 
16590  /* check if the constraint got redundant or infeasible */
16591  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16592  {
16593  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16594  {
16595  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16596  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16597  cutoff = TRUE;
16598  }
16599  else
16600  {
16601  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16602  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16603  SCIP_CALL( SCIPdelCons(scip, cons) );
16604  assert(!SCIPconsIsActive(cons));
16605 
16606  if( !consdata->upgraded )
16607  (*ndelconss)++;
16608  }
16609  }
16610  }
16611 
16612  /* convert special equalities */
16613  if( !cutoff && SCIPconsIsActive(cons) )
16614  {
16615  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16616  }
16617 
16618  /* apply dual presolving for variables that appear in only one constraint */
16619  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16620  {
16621  SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16622  }
16623 
16624  /* check if an inequality is parallel to the objective function */
16625  if( !cutoff && SCIPconsIsActive(cons) )
16626  {
16627  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16628  }
16629 
16630  /* remember the first changed constraint to begin the next aggregation round with */
16631  if( firstchange == INT_MAX && consdata->changed )
16632  firstchange = c;
16633 
16634  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16635  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16636  firstupgradetry = c;
16637  }
16638 
16639  /* singleton column stuffing */
16640  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16641  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16642  {
16643  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16644  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16645 
16646  /* handle empty constraint */
16647  if( consdata->nvars == 0 )
16648  {
16649  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16650  {
16651  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16652  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16653  cutoff = TRUE;
16654  }
16655  else
16656  {
16657  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16658  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16659  SCIP_CALL( SCIPdelCons(scip, cons) );
16660  assert(!SCIPconsIsActive(cons));
16661 
16662  if( !consdata->upgraded )
16663  (*ndelconss)++;
16664  }
16665  break;
16666  }
16667  }
16668  }
16669 
16670  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16671  * only apply this expensive procedure in exhaustive presolving timing
16672  */
16673  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16674  {
16675  assert(firstchange >= 0);
16676 
16677  if( firstchange < nconss && conshdlrdata->presolusehashing )
16678  {
16679  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16680  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16681  ndelconss, nchgsides) );
16682  }
16683 
16684  if( firstchange < nconss && conshdlrdata->presolpairwise )
16685  {
16686  SCIP_CONS** usefulconss;
16687  int nusefulconss;
16688  int firstchangenew;
16689  SCIP_Longint npaircomparisons;
16690 
16691  npaircomparisons = 0;
16692  oldndelconss = *ndelconss;
16693  oldnchgsides = *nchgsides;
16694  oldnchgcoefs = *nchgcoefs;
16695 
16696  /* allocate temporary memory */
16697  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16698 
16699  nusefulconss = 0;
16700  firstchangenew = -1;
16701  for( c = 0; c < nconss; ++c )
16702  {
16703  /* update firstchange */
16704  if( c == firstchange )
16705  firstchangenew = nusefulconss;
16706 
16707  /* ignore inactive and modifiable constraints */
16708  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16709  continue;
16710 
16711  usefulconss[nusefulconss] = conss[c];
16712  ++nusefulconss;
16713  }
16714  firstchange = firstchangenew;
16715  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16716 
16717  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16718  {
16719  /* constraint has become inactive or modifiable during pairwise presolving */
16720  if( usefulconss[c] == NULL )
16721  continue;
16722 
16723  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16724 
16725  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16726  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16727  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16728 
16729  if( npaircomparisons > conshdlrdata->nmincomparisons )
16730  {
16731  assert(npaircomparisons > 0);
16732  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16733  break;
16734  oldndelconss = *ndelconss;
16735  oldnchgsides = *nchgsides;
16736  oldnchgcoefs = *nchgcoefs;
16737  npaircomparisons = 0;
16738  }
16739  }
16740  /* free temporary memory */
16741  SCIPfreeBufferArray(scip, &usefulconss);
16742  }
16743  }
16744 
16745  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16746  * in linear constraints and we therefore have full information about it
16747  */
16748  if( !cutoff && firstupgradetry < nconss
16749  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16750  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16751  )
16752  {
16753  if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16754  {
16755  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16756  }
16757  }
16758 
16759  /* try to upgrade constraints into a more specific constraint type;
16760  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16761  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16762  */
16763  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16764  {
16765  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16766  {
16767  cons = conss[c];
16768 
16769  /* don't upgrade modifiable constraints */
16770  if( SCIPconsIsModifiable(cons) )
16771  continue;
16772 
16773  consdata = SCIPconsGetData(cons);
16774  assert(consdata != NULL);
16775 
16776  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16777  if( consdata->upgradetried )
16778  continue;
16779  /* @todo force that upgrade will be performed later? */
16780  if( !consdata->presolved )
16781  continue;
16782 
16783  consdata->upgradetried = TRUE;
16784  if( SCIPconsIsActive(cons) )
16785  {
16786  SCIP_CONS* upgdcons;
16787 
16788  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16789  if( upgdcons != NULL )
16790  {
16791  /* add the upgraded constraint to the problem */
16792  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16793  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16794  (*nupgdconss)++;
16795 
16796  /* mark the linear constraint being upgraded and to be removed after presolving;
16797  * don't delete it directly, because it may help to preprocess other linear constraints
16798  */
16799  assert(!consdata->upgraded);
16800  consdata->upgraded = TRUE;
16801 
16802  /* delete upgraded inequalities immediately;
16803  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16804  */
16805  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16806  || !conshdlrdata->presolpairwise
16807  || (conshdlrdata->maxaggrnormscale == 0.0) )
16808  {
16809  SCIP_CALL( SCIPdelCons(scip, cons) );
16810  }
16811  }
16812  }
16813  }
16814  }
16815 
16816  /* return the correct result code */
16817  if( cutoff )
16818  *result = SCIP_CUTOFF;
16819  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16820  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16821  *result = SCIP_SUCCESS;
16822  else
16823  *result = SCIP_DIDNOTFIND;
16824 
16825  return SCIP_OKAY;
16826 }
16827 
16828 
16829 /** propagation conflict resolving method of constraint handler */
16830 static
16831 SCIP_DECL_CONSRESPROP(consRespropLinear)
16832 { /*lint --e{715}*/
16833  assert(scip != NULL);
16834  assert(cons != NULL);
16835  assert(result != NULL);
16836 
16837  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16838 
16839  return SCIP_OKAY;
16840 }
16841 
16842 
16843 /** variable rounding lock method of constraint handler */
16844 static
16845 SCIP_DECL_CONSLOCK(consLockLinear)
16846 { /*lint --e{715}*/
16847  SCIP_CONSDATA* consdata;
16848  SCIP_Bool haslhs;
16849  SCIP_Bool hasrhs;
16850  int i;
16851 
16852  assert(scip != NULL);
16853  assert(cons != NULL);
16854  consdata = SCIPconsGetData(cons);
16855  assert(consdata != NULL);
16856 
16857  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16858  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16859 
16860  /* update rounding locks of every single variable */
16861  for( i = 0; i < consdata->nvars; ++i )
16862  {
16863  if( SCIPisPositive(scip, consdata->vals[i]) )
16864  {
16865  if( haslhs )
16866  {
16867  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16868  }
16869  if( hasrhs )
16870  {
16871  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16872  }
16873  }
16874  else
16875  {
16876  if( haslhs )
16877  {
16878  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16879  }
16880  if( hasrhs )
16881  {
16882  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16883  }
16884  }
16885  }
16886 
16887  return SCIP_OKAY;
16888 }
16889 
16890 
16891 /** variable deletion method of constraint handler */
16892 static
16893 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16894 {
16895  assert(scip != NULL);
16896  assert(conshdlr != NULL);
16897  assert(conss != NULL || nconss == 0);
16898 
16899  if( nconss > 0 )
16900  {
16901  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16902  }
16903 
16904  return SCIP_OKAY;
16905 }
16906 
16907 /** constraint display method of constraint handler */
16908 static
16909 SCIP_DECL_CONSPRINT(consPrintLinear)
16910 { /*lint --e{715}*/
16911  assert(scip != NULL);
16912  assert(conshdlr != NULL);
16913  assert(cons != NULL);
16914 
16915  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16916 
16917  return SCIP_OKAY;
16918 }
16919 
16920 /** constraint copying method of constraint handler */
16921 static
16922 SCIP_DECL_CONSCOPY(consCopyLinear)
16923 { /*lint --e{715}*/
16924  SCIP_VAR** sourcevars;
16925  SCIP_Real* sourcecoefs;
16926  const char* consname;
16927  int nvars;
16929  assert(scip != NULL);
16930  assert(sourcescip != NULL);
16931  assert(sourcecons != NULL);
16932 
16933  /* get variables and coefficients of the source constraint */
16934  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16935  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16936  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16937 
16938  if( name != NULL )
16939  consname = name;
16940  else
16941  consname = SCIPconsGetName(sourcecons);
16942 
16943  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16944  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16945  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16946  assert(cons != NULL || *valid == FALSE);
16947 
16948  /* @todo should also the checkabsolute flag of the constraint be copied? */
16949 
16950  return SCIP_OKAY;
16951 }
16952 
16953 /** find operators '<=', '==', '>=', [free] in input string and return those places
16954  *
16955  * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16956  */
16957 static
16958 void findOperators(
16959  const char* str, /**< null terminated input string */
16960  char** firstoperator, /**< pointer to store the string starting at the first operator */
16961  char** secondoperator, /**< pointer to store the string starting at the second operator */
16962  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16963  )
16964 {
16965  char* curr;
16966 
16967  assert(str != NULL);
16968  assert(firstoperator != NULL);
16969  assert(secondoperator != NULL);
16970 
16971  *firstoperator = NULL;
16972  *secondoperator = NULL;
16973 
16974  curr = (char*)str;
16975  *success = TRUE;
16976 
16977  /* loop over the input string to find all operators */
16978  while( *curr && *success )
16979  {
16980  SCIP_Bool found = FALSE;
16981  int increment = 1;
16982 
16983  /* try if we found a possible operator */
16984  switch( *curr )
16985  {
16986  case '<':
16987  case '=':
16988  case '>':
16989 
16990  /* check if the two characters curr[0,1] form an operator together */
16991  if( curr[1] == '=' )
16992  {
16993  found = TRUE;
16994 
16995  /* update increment to continue after this operator */
16996  increment = 2;
16997  }
16998  break;
16999  case '[':
17000  if( strncmp(curr, "[free]", 6) == 0 )
17001  {
17002  found = TRUE;
17003 
17004  /* update increment to continue after this operator */
17005  increment = 6;
17006  }
17007  break;
17008  default:
17009  break;
17010  }
17011 
17012  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17013  if( found )
17014  {
17015  if( *firstoperator == NULL )
17016  {
17017  *firstoperator = curr;
17018  }
17019  else
17020  {
17021  if( *secondoperator != NULL )
17022  {
17023  SCIPerrorMessage("Found more than two operators in line %s\n", str);
17024  *success = FALSE;
17025  }
17026  else if( strncmp(*firstoperator, "<=", 2) != 0 )
17027  {
17028  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17029  *success = FALSE;
17030  }
17031  else if( strncmp(curr, "<=", 2) != 0 )
17032  {
17033  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17034  *success = FALSE;
17035  }
17036 
17037  *secondoperator = curr;
17038  }
17039  }
17040 
17041  curr += increment;
17042  }
17043 
17044  /* check if we did find at least one operator */
17045  if( *success )
17046  {
17047  if( *firstoperator == NULL )
17048  {
17049  SCIPerrorMessage("Could not find any operator in line %s\n", str);
17050  *success = FALSE;
17051  }
17052  }
17053 }
17054 
17055 /** constraint parsing method of constraint handler */
17056 static
17057 SCIP_DECL_CONSPARSE(consParseLinear)
17058 { /*lint --e{715}*/
17059  SCIP_VAR** vars;
17060  SCIP_Real* coefs;
17061  int nvars;
17062  int coefssize;
17063  int requsize;
17064  SCIP_Real lhs;
17065  SCIP_Real rhs;
17066  char* endptr;
17067  char* firstop;
17068  char* secondop;
17069  SCIP_Bool operatorsuccess;
17070  char* lhsstrptr;
17071  char* rhsstrptr;
17072  char* varstrptr;
17073 
17074  assert(scip != NULL);
17075  assert(success != NULL);
17076  assert(str != NULL);
17077  assert(name != NULL);
17078  assert(cons != NULL);
17079 
17080  /* set left and right hand side to their default values */
17081  lhs = -SCIPinfinity(scip);
17082  rhs = SCIPinfinity(scip);
17083 
17084  (*success) = FALSE;
17085 
17086  /* return of string empty */
17087  if( !*str )
17088  return SCIP_OKAY;
17089 
17090  /* ignore whitespace */
17091  SCIP_CALL( SCIPskipSpace((char**)&str) );
17092 
17093  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17094  * and the special word [free]
17095  */
17096  findOperators(str, &firstop, &secondop, &operatorsuccess);
17097 
17098  /* if the grammar is not valid for parsing a linear constraint, return */
17099  if( ! operatorsuccess )
17100  return SCIP_OKAY;
17101 
17102  varstrptr = (char *)str;
17103  lhsstrptr = rhsstrptr = NULL;
17104  assert(firstop != NULL);
17105 
17106  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17107  switch( *firstop )
17108  {
17109  case '<':
17110  assert(firstop[1] == '=');
17111  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17112  if( secondop != NULL )
17113  {
17114  assert(secondop[0] == '<' && secondop[1] == '=');
17115  lhsstrptr = (char *)str;
17116  varstrptr = firstop + 2;
17117  rhsstrptr = secondop + 2;
17118  }
17119  else
17120  {
17121  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17122  lhsstrptr = NULL;
17123  varstrptr = (char *)str;
17124  rhsstrptr = firstop + 2;
17125  }
17126  break;
17127  case '>':
17128  assert(firstop[1] == '=');
17129  assert(secondop == NULL);
17130  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17131  lhsstrptr = firstop + 2;
17132  break;
17133  case '=':
17134  assert(firstop[1] == '=');
17135  assert(secondop == NULL);
17136  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17137  rhsstrptr = firstop + 2;
17138  lhsstrptr = firstop + 2;
17139  break;
17140  case '[':
17141  assert(strncmp(firstop, "[free]", 6) == 0);
17142  assert(secondop == NULL);
17143  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17144  break;
17145  default:
17146  /* it should not be possible that a different character appears in that position */
17147  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17148  return SCIP_READERROR;
17149  }
17150 
17151  /* parse left hand side, if necessary */
17152  if( lhsstrptr != NULL )
17153  {
17154  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17155  {
17156  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17157  return SCIP_OKAY;
17158  }
17159 
17160  /* in case of an equation, assign the left also to the right hand side */
17161  if( rhsstrptr == lhsstrptr )
17162  rhs = lhs;
17163  }
17164 
17165  /* parse right hand side, if different from left hand side */
17166  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17167  {
17168  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17169  {
17170  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17171  return SCIP_OKAY;
17172  }
17173  }
17174 
17175  /* initialize buffers for storing the variables and coefficients */
17176  coefssize = 100;
17177  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17178  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17179 
17180  assert(varstrptr != NULL);
17181 
17182  /* parse linear sum to get variables and coefficients */
17183  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17184 
17185  if( *success && requsize > coefssize )
17186  {
17187  /* realloc buffers and try again */
17188  coefssize = requsize;
17189  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17190  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17191 
17192  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17193  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17194  }
17195 
17196  if( !*success )
17197  {
17198  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17199  }
17200  else
17201  {
17202  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17203  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17204  }
17205 
17206  SCIPfreeBufferArray(scip, &coefs);
17207  SCIPfreeBufferArray(scip, &vars);
17208 
17209  return SCIP_OKAY;
17210 }
17211 
17212 
17213 /** constraint method of constraint handler which returns the variables (if possible) */
17214 static
17215 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17216 { /*lint --e{715}*/
17217  SCIP_CONSDATA* consdata;
17218 
17219  consdata = SCIPconsGetData(cons);
17220  assert(consdata != NULL);
17221 
17222  if( varssize < consdata->nvars )
17223  (*success) = FALSE;
17224  else
17225  {
17226  assert(vars != NULL);
17227 
17228  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17229  (*success) = TRUE;
17230  }
17231 
17232  return SCIP_OKAY;
17233 }
17235 /**! [Callback for the number of variables]*/
17236 /** constraint method of constraint handler which returns the number of variables (if possible) */
17237 static
17238 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17239 { /*lint --e{715}*/
17240  SCIP_CONSDATA* consdata;
17241 
17242  consdata = SCIPconsGetData(cons);
17243  assert(consdata != NULL);
17244 
17245  (*nvars) = consdata->nvars;
17246  (*success) = TRUE;
17247 
17248  return SCIP_OKAY;
17249 }
17250 /**! [Callback for the number of variables]*/
17251 
17252 /*
17253  * Callback methods of event handler
17254  */
17255 
17256 /** execution method of event handler */
17257 static
17258 SCIP_DECL_EVENTEXEC(eventExecLinear)
17259 { /*lint --e{715}*/
17260  SCIP_CONS* cons;
17261  SCIP_CONSDATA* consdata;
17262  SCIP_VAR* var;
17263  SCIP_EVENTTYPE eventtype;
17264 
17265  assert(scip != NULL);
17266  assert(eventhdlr != NULL);
17267  assert(eventdata != NULL);
17268  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17269  assert(event != NULL);
17270 
17271  cons = eventdata->cons;
17272  assert(cons != NULL);
17273  consdata = SCIPconsGetData(cons);
17274  assert(consdata != NULL);
17275 
17276  /* we can skip events droped for deleted constraints */
17277  if( SCIPconsIsDeleted(cons) )
17278  return SCIP_OKAY;
17279 
17280  eventtype = SCIPeventGetType(event);
17281  var = SCIPeventGetVar(event);
17282 
17283  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17284  {
17285  SCIP_Real oldbound;
17286  SCIP_Real newbound;
17287  SCIP_Real val;
17288  int varpos;
17289 
17290  varpos = eventdata->varpos;
17291  assert(0 <= varpos && varpos < consdata->nvars);
17292  oldbound = SCIPeventGetOldbound(event);
17293  newbound = SCIPeventGetNewbound(event);
17294  assert(var != NULL);
17295  assert(consdata->vars[varpos] == var);
17296  val = consdata->vals[varpos];
17297 
17298  /* we only need to update the activities if the constraint is active,
17299  * otherwise we mark them to be invalid
17300  */
17301  if( SCIPconsIsActive(cons) )
17302  {
17303  /* update the activity values */
17304  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17305  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17306  else
17307  {
17308  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17309  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17310  }
17311  }
17312  else
17313  consdataInvalidateActivities(consdata);
17314 
17315  consdata->presolved = FALSE;
17316  consdata->rangedrowpropagated = 0;
17317 
17318  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17319  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17320  {
17321  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17322 
17323  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17324  if( consdata->maxactdeltavar == var )
17325  {
17326  consdata->maxactdelta = SCIP_INVALID;
17327  consdata->maxactdeltavar = NULL;
17328  }
17329 
17330  /* check whether bound tightening might now be successful */
17331  if( consdata->boundstightened > 0)
17332  {
17333  switch( eventtype )
17334  {
17336  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17337  consdata->boundstightened = 0;
17338  break;
17340  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17341  consdata->boundstightened = 0;
17342  break;
17343  default:
17344  SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17345  return SCIP_INVALIDDATA;
17346  }
17347  }
17348  }
17349  /* update maximal activity delta if a bound was relaxed */
17350  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17351  {
17352  SCIP_Real lb;
17353  SCIP_Real ub;
17354  SCIP_Real domain;
17355  SCIP_Real delta;
17356 
17357  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17358 
17359  lb = SCIPvarGetLbLocal(var);
17360  ub = SCIPvarGetUbLocal(var);
17361 
17362  domain = ub - lb;
17363  delta = REALABS(val) * domain;
17364 
17365  if( delta > consdata->maxactdelta )
17366  {
17367  consdata->maxactdelta = delta;
17368  consdata->maxactdeltavar = var;
17369  }
17370  }
17371  }
17372  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17373  {
17374  /* we want to remove the fixed variable */
17375  consdata->presolved = FALSE;
17376  consdata->removedfixings = FALSE;
17377  consdata->rangedrowpropagated = 0;
17378 
17379  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17380  if( consdata->maxactdeltavar == var )
17381  {
17382  consdata->maxactdelta = SCIP_INVALID;
17383  consdata->maxactdeltavar = NULL;
17384  }
17385  }
17386  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17387  {
17388  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17389  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17390  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17391  consdata->presolved = FALSE;
17392  }
17393  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17394  {
17395  SCIP_Real oldbound;
17396  SCIP_Real newbound;
17397  SCIP_Real val;
17398  int varpos;
17399 
17400  varpos = eventdata->varpos;
17401  assert(0 <= varpos && varpos < consdata->nvars);
17402  oldbound = SCIPeventGetOldbound(event);
17403  newbound = SCIPeventGetNewbound(event);
17404  assert(var != NULL);
17405  assert(consdata->vars[varpos] == var);
17406  val = consdata->vals[varpos];
17407 
17408  consdata->rangedrowpropagated = 0;
17409 
17410  /* update the activity values */
17411  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17412  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17413  else
17414  {
17415  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17416  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17417  }
17418 
17419  /* if the variable is binary but not fixed it had to become binary due to this global change */
17420  if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17421  {
17422  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17423  consdata->indexsorted = FALSE;
17424  else
17425  consdata->coefsorted = FALSE;
17426  }
17427  }
17428  else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17429  {
17430  assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17431 
17432  /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17433  consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17434 
17435  /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17436  consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17437  }
17438  else
17439  {
17440  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17441  consdata->varsdeleted = TRUE;
17442  }
17443 
17444  return SCIP_OKAY;
17445 }
17446 
17447 
17448 /*
17449  * Callback methods of conflict handler
17450  */
17451 
17452 /** conflict processing method of conflict handler (called when conflict was found) */
17453 static
17454 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17455 { /*lint --e{715}*/
17456  SCIP_VAR** vars;
17457  SCIP_Real* vals;
17458  SCIP_Real lhs;
17459  int i;
17460 
17461  assert(scip != NULL);
17462  assert(conflicthdlr != NULL);
17463  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17464  assert(bdchginfos != NULL || nbdchginfos == 0);
17465  assert(result != NULL);
17466 
17467  /* don't process already resolved conflicts */
17468  if( resolved )
17469  {
17470  *result = SCIP_DIDNOTRUN;
17471  return SCIP_OKAY;
17472  }
17474  *result = SCIP_DIDNOTFIND;
17475 
17476  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17477  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17478  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17479  lhs = 1.0;
17480  for( i = 0; i < nbdchginfos; ++i )
17481  {
17482  assert(bdchginfos != NULL);
17483 
17484  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17485 
17486  /* we can only treat binary variables */
17487  /**@todo extend linear conflict constraints to some non-binary cases */
17488  if( !SCIPvarIsBinary(vars[i]) )
17489  break;
17490 
17491  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17492  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17493  vals[i] = 1.0;
17494  else
17495  {
17496  vals[i] = -1.0;
17497  lhs -= 1.0;
17498  }
17499  }
17500 
17501  if( i == nbdchginfos )
17502  {
17503  SCIP_CONS* cons;
17504  SCIP_CONS* upgdcons;
17505  char consname[SCIP_MAXSTRLEN];
17506 
17507  /* create a constraint out of the conflict set */
17508  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17509  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17510  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17511 
17512  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17513  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17514  if( upgdcons != NULL )
17515  {
17516  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17517  cons = upgdcons;
17518  }
17519 
17520  /* add conflict to SCIP */
17521  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17522 
17523  *result = SCIP_CONSADDED;
17524  }
17525 
17526  /* free temporary memory */
17527  SCIPfreeBufferArray(scip, &vals);
17528  SCIPfreeBufferArray(scip, &vars);
17529 
17530  return SCIP_OKAY;
17531 }
17532 
17533 
17534 /*
17535  * Nonlinear constraint upgrading
17536  */
17537 
17538 /** tries to upgrade a nonlinear constraint into a linear constraint */
17539 static
17540 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17541 {
17542  SCIP_CONSDATA* consdata;
17543  SCIP_EXPR* expr;
17544  SCIP_Real lhs;
17545  SCIP_Real rhs;
17546  int i;
17547 
17548  assert(nupgdconss != NULL);
17549  assert(upgdconss != NULL);
17550  assert(upgdconsssize > 0);
17551 
17552  expr = SCIPgetExprNonlinear(cons);
17553  assert(expr != NULL);
17554 
17555  /* not a linear constraint if the expression is not a sum
17556  * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17557  */
17558  if( !SCIPisExprSum(scip, expr) )
17559  return SCIP_OKAY;
17560 
17561  /* if at least one child is not a variable, then not a linear constraint */
17562  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17563  if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17564  return SCIP_OKAY;
17565 
17566  /* consider constant part of the sum expression */
17567  lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17568  rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17569 
17570  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17571  0, NULL, NULL, lhs, rhs,
17575  SCIPconsIsStickingAtNode(cons)) );
17576  assert(upgdconss[0] != NULL);
17577 
17578  consdata = SCIPconsGetData(upgdconss[0]);
17579 
17580  /* add linear terms */
17581  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) );
17582  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17583  {
17584  SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) );
17585  }
17586 
17587  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17588  consdata->checkabsolute = TRUE;
17589 
17590  *nupgdconss = 1;
17591 
17592  SCIPdebugMsg(scip, "created linear constraint:\n");
17593  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17594 
17595  return SCIP_OKAY;
17596 } /*lint !e715*/
17597 
17598 /*
17599  * constraint specific interface methods
17600  */
17601 
17602 /** creates the handler for linear constraints and includes it in SCIP */
17604  SCIP* scip /**< SCIP data structure */
17605  )
17606 {
17607  SCIP_CONSHDLRDATA* conshdlrdata;
17608  SCIP_CONSHDLR* conshdlr;
17609  SCIP_EVENTHDLR* eventhdlr;
17610  SCIP_CONFLICTHDLR* conflicthdlr;
17611 
17612  assert(scip != NULL);
17613 
17614  /* create event handler for bound change events */
17616  eventExecLinear, NULL) );
17617 
17618  /* create conflict handler for linear constraints */
17620  conflictExecLinear, NULL) );
17621 
17622  /* create constraint handler data */
17623  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17624 
17625  /* include constraint handler */
17628  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17629  conshdlrdata) );
17630 
17631  assert(conshdlr != NULL);
17632 
17633  /* set non-fundamental callbacks via specific setter functions */
17634  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17635  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17636  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17637  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17638  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17639  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17640  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17641  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17642  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17643  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17644  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17645  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17646  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17647  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17648  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17649  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17650  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17651  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17653  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17654  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17656  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17657  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17658 
17659  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17660  {
17661  /* include the linear constraint upgrade in the nonlinear constraint handler */
17663  }
17664 
17665  /* add linear constraint handler parameters */
17666  SCIP_CALL( SCIPaddIntParam(scip,
17667  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17668  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17669  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17670  SCIP_CALL( SCIPaddIntParam(scip,
17671  "constraints/" CONSHDLR_NAME "/maxrounds",
17672  "maximal number of separation rounds per node (-1: unlimited)",
17673  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17674  SCIP_CALL( SCIPaddIntParam(scip,
17675  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17676  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17677  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17678  SCIP_CALL( SCIPaddIntParam(scip,
17679  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17680  "maximal number of cuts separated per separation round",
17681  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17682  SCIP_CALL( SCIPaddIntParam(scip,
17683  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17684  "maximal number of cuts separated per separation round in the root node",
17685  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17687  "constraints/" CONSHDLR_NAME "/presolpairwise",
17688  "should pairwise constraint comparison be performed in presolving?",
17689  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17691  "constraints/" CONSHDLR_NAME "/presolusehashing",
17692  "should hash table be used for detecting redundant constraints in advance",
17693  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17694  SCIP_CALL( SCIPaddIntParam(scip,
17695  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17696  "number for minimal pairwise presolve comparisons",
17697  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17699  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17700  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17701  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17703  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17704  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17705  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17707  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17708  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17709  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17711  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17712  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17713  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17715  "constraints/" CONSHDLR_NAME "/separateall",
17716  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17717  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17719  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17720  "should presolving search for aggregations in equations",
17721  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17723  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17724  "should presolving try to simplify inequalities",
17725  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17727  "constraints/" CONSHDLR_NAME "/dualpresolving",
17728  "should dual presolving steps be performed?",
17729  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17731  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17732  "should stuffing of singleton continuous variables be performed?",
17733  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17735  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17736  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17737  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17739  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17740  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17742  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17743  "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)?",
17744  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17746  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17747  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17748  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17750  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17751  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17752  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17754  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17755  "should presolving try to detect subsets of constraints parallel to the objective function?",
17756  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17758  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17759  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17760  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17762  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17763  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17764  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17765  SCIP_CALL( SCIPaddIntParam(scip,
17766  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17767  "maximum depth to apply ranged row propagation",
17768  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17769  SCIP_CALL( SCIPaddIntParam(scip,
17770  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17771  "frequency for applying ranged row propagation",
17772  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17774  "constraints/" CONSHDLR_NAME "/multaggrremove",
17775  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17776  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17778  "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17779  "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17780  &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17782  "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17783  "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17784  &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17786  "constraints/" CONSHDLR_NAME "/extractcliques",
17787  "should Cliques be extracted?",
17788  &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17789 
17790  return SCIP_OKAY;
17791 }
17792 
17793 /** includes a linear constraint update method into the linear constraint handler */
17795  SCIP* scip, /**< SCIP data structure */
17796  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17797  int priority, /**< priority of upgrading method */
17798  const char* conshdlrname /**< name of the constraint handler */
17799  )
17800 {
17801  SCIP_CONSHDLR* conshdlr;
17802  SCIP_CONSHDLRDATA* conshdlrdata;
17803  SCIP_LINCONSUPGRADE* linconsupgrade;
17804  char paramname[SCIP_MAXSTRLEN];
17805  char paramdesc[SCIP_MAXSTRLEN];
17806 
17807  assert(scip != NULL);
17808  assert(linconsupgd != NULL);
17809  assert(conshdlrname != NULL );
17810 
17811  /* find the linear constraint handler */
17812  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17813  if( conshdlr == NULL )
17814  {
17815  SCIPerrorMessage("linear constraint handler not found\n");
17816  return SCIP_PLUGINNOTFOUND;
17817  }
17818 
17819  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17820  assert(conshdlrdata != NULL);
17821 
17822  /* check if linear constraint update method already exists in constraint handler data */
17823  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17824  {
17825  /* create a linear constraint upgrade data object */
17826  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17827 
17828  /* insert linear constraint update method into constraint handler data */
17829  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17830 
17831  /* adds parameter to turn on and off the upgrading step */
17832  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17833  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17835  paramname, paramdesc,
17836  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17837  }
17838 
17839  return SCIP_OKAY;
17840 }
17841 
17842 /** creates and captures a linear constraint
17843  *
17844  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17845  */
17847  SCIP* scip, /**< SCIP data structure */
17848  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17849  const char* name, /**< name of constraint */
17850  int nvars, /**< number of nonzeros in the constraint */
17851  SCIP_VAR** vars, /**< array with variables of constraint entries */
17852  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17853  SCIP_Real lhs, /**< left hand side of constraint */
17854  SCIP_Real rhs, /**< right hand side of constraint */
17855  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17856  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17857  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17858  * Usually set to TRUE. */
17859  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17860  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17861  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17862  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17863  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17864  * Usually set to TRUE. */
17865  SCIP_Bool local, /**< is constraint only valid locally?
17866  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17867  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17868  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17869  * adds coefficients to this constraint. */
17870  SCIP_Bool dynamic, /**< is constraint subject to aging?
17871  * Usually set to FALSE. Set to TRUE for own cuts which
17872  * are separated as constraints. */
17873  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17874  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17875  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17876  * if it may be moved to a more global node?
17877  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17878  )
17879 {
17880  SCIP_CONSHDLR* conshdlr;
17881  SCIP_CONSDATA* consdata;
17882 
17883  assert(scip != NULL);
17884  assert(cons != NULL);
17885 
17886  /* find the linear constraint handler */
17887  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17888  if( conshdlr == NULL )
17889  {
17890  SCIPerrorMessage("linear constraint handler not found\n");
17891  return SCIP_PLUGINNOTFOUND;
17892  }
17893 
17894  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17895  * constraint after presolving we have to ensure that it holds active variables
17896  */
17897  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17898  {
17899  SCIP_VAR** consvars;
17900  SCIP_Real* consvals;
17901  SCIP_Real constant = 0.0;
17902  int nconsvars;
17903  int requiredsize;
17904 
17905  nconsvars = nvars;
17906  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17907  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17908 
17909  /* get active variables for new constraint */
17910  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17911 
17912  /* if space was not enough we need to resize the buffers */
17913  if( requiredsize > nconsvars )
17914  {
17915  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17916  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17917 
17918  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17919  assert(requiredsize <= nconsvars);
17920  }
17921 
17922  /* adjust sides and check that we do not subtract infinity values */
17923  if( SCIPisInfinity(scip, REALABS(constant)) )
17924  {
17925  if( constant < 0.0 )
17926  {
17927  if( SCIPisInfinity(scip, lhs) )
17928  {
17929  SCIPfreeBufferArray(scip, &consvals);
17930  SCIPfreeBufferArray(scip, &consvars);
17931 
17932  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);
17933 
17934  SCIPABORT();
17935  return SCIP_INVALIDDATA; /*lint !e527*/
17936  }
17937  if( SCIPisInfinity(scip, rhs) )
17938  {
17939  SCIPfreeBufferArray(scip, &consvals);
17940  SCIPfreeBufferArray(scip, &consvars);
17941 
17942  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);
17943 
17944  SCIPABORT();
17945  return SCIP_INVALIDDATA; /*lint !e527*/
17946  }
17947 
17948  lhs = -SCIPinfinity(scip);
17949  rhs = -SCIPinfinity(scip);
17950  }
17951  else
17952  {
17953  if( SCIPisInfinity(scip, -lhs) )
17954  {
17955  SCIPfreeBufferArray(scip, &consvals);
17956  SCIPfreeBufferArray(scip, &consvars);
17957 
17958  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);
17959 
17960  SCIPABORT();
17961  return SCIP_INVALIDDATA; /*lint !e527*/
17962  }
17963  if( SCIPisInfinity(scip, -rhs) )
17964  {
17965  SCIPfreeBufferArray(scip, &consvals);
17966  SCIPfreeBufferArray(scip, &consvars);
17967 
17968  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);
17969 
17970  SCIPABORT();
17971  return SCIP_INVALIDDATA; /*lint !e527*/
17972  }
17973 
17974  lhs = SCIPinfinity(scip);
17975  rhs = SCIPinfinity(scip);
17976  }
17977  }
17978  else
17979  {
17980  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17981  lhs -= constant;
17982  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17983  rhs -= constant;
17984 
17985  if( SCIPisInfinity(scip, -lhs) )
17986  lhs = -SCIPinfinity(scip);
17987  else if( SCIPisInfinity(scip, lhs) )
17988  lhs = SCIPinfinity(scip);
17989 
17990  if( SCIPisInfinity(scip, rhs) )
17991  rhs = SCIPinfinity(scip);
17992  else if( SCIPisInfinity(scip, -rhs) )
17993  rhs = -SCIPinfinity(scip);
17994  }
17995 
17996  /* create constraint data */
17997  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17998  assert(consdata != NULL);
17999 
18000  SCIPfreeBufferArray(scip, &consvals);
18001  SCIPfreeBufferArray(scip, &consvars);
18002  }
18003  else
18004  {
18005  /* create constraint data */
18006  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18007  assert(consdata != NULL);
18008  }
18009 
18010 #ifndef NDEBUG
18011  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18012  if( check || enforce )
18013  {
18014  int n;
18015  for(n = consdata->nvars - 1; n >= 0; --n )
18016  assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18017  }
18018 #endif
18019 
18020  /* create constraint */
18021  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18022  local, modifiable, dynamic, removable, stickingatnode) );
18023 
18024  return SCIP_OKAY;
18025 }
18026 
18027 /** creates and captures a linear constraint
18028  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18029  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18030  *
18031  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18032  *
18033  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18034  */
18036  SCIP* scip, /**< SCIP data structure */
18037  SCIP_CONS** cons, /**< pointer to hold the created constraint */
18038  const char* name, /**< name of constraint */
18039  int nvars, /**< number of nonzeros in the constraint */
18040  SCIP_VAR** vars, /**< array with variables of constraint entries */
18041  SCIP_Real* vals, /**< array with coefficients of constraint entries */
18042  SCIP_Real lhs, /**< left hand side of constraint */
18043  SCIP_Real rhs /**< right hand side of constraint */
18044  )
18045 {
18046  assert(scip != NULL);
18047 
18048  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18049  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
18050 
18051  return SCIP_OKAY;
18052 }
18053 
18054 /** creates by copying and captures a linear constraint */
18056  SCIP* scip, /**< target SCIP data structure */
18057  SCIP_CONS** cons, /**< pointer to store the created target constraint */
18058  SCIP* sourcescip, /**< source SCIP data structure */
18059  const char* name, /**< name of constraint */
18060  int nvars, /**< number of variables in source variable array */
18061  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18062  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18063  SCIP_Real lhs, /**< left hand side of the linear constraint */
18064  SCIP_Real rhs, /**< right hand side of the linear constraint */
18065  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18066  * variables of the target SCIP */
18067  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18068  * target constraints */
18069  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18070  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18071  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18072  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18073  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18074  SCIP_Bool local, /**< is constraint only valid locally? */
18075  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18076  SCIP_Bool dynamic, /**< is constraint subject to aging? */
18077  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18078  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18079  * if it may be moved to a more global node? */
18080  SCIP_Bool global, /**< create a global or a local copy? */
18081  SCIP_Bool* valid /**< pointer to store if the copying was valid */
18082  )
18083 {
18084  SCIP_VAR** vars;
18085  SCIP_Real* coefs;
18086 
18087  SCIP_Real constant;
18088  int requiredsize;
18089  int v;
18090  SCIP_Bool success;
18091 
18092  if( SCIPisGT(scip, lhs, rhs) )
18093  {
18094  *valid = FALSE;
18095  return SCIP_OKAY;
18096  }
18097 
18098  (*valid) = TRUE;
18099 
18100  if( nvars == 0 )
18101  {
18102  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18103  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18104  return SCIP_OKAY;
18105  }
18106 
18107  /* duplicate variable array */
18108  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18109 
18110  /* duplicate coefficient array */
18111  if( sourcecoefs != NULL )
18112  {
18113  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18114  }
18115  else
18116  {
18117  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18118  for( v = 0; v < nvars; ++v )
18119  coefs[v] = 1.0;
18120  }
18121 
18122  constant = 0.0;
18123 
18124  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18125  * the target SCIP
18126  */
18127  if( !SCIPvarIsOriginal(vars[0]) )
18128  {
18129  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18130 
18131  if( requiredsize > nvars )
18132  {
18133  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18134  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18135 
18136  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18137  assert(requiredsize <= nvars);
18138  }
18139  }
18140  else
18141  {
18142  for( v = 0; v < nvars; ++v )
18143  {
18144  assert(SCIPvarIsOriginal(vars[v]));
18145  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18146  assert(vars[v] != NULL);
18147  }
18148  }
18149 
18150  success = TRUE;
18151  /* map variables of the source constraint to variables of the target SCIP */
18152  for( v = 0; v < nvars && success; ++v )
18153  {
18154  SCIP_VAR* var;
18155  var = vars[v];
18156 
18157  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18158  assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18159 
18160  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18161  assert(!(success) || vars[v] != NULL);
18162  }
18163 
18164  /* only create the target constraint, if all variables could be copied */
18165  if( success )
18166  {
18167  if( !SCIPisInfinity(scip, -lhs) )
18168  lhs -= constant;
18169 
18170  if( !SCIPisInfinity(scip, rhs) )
18171  rhs -= constant;
18172 
18173  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18174  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18175  }
18176  else
18177  *valid = FALSE;
18178 
18179  /* free buffer array */
18180  SCIPfreeBufferArray(scip, &coefs);
18181  SCIPfreeBufferArray(scip, &vars);
18182 
18183  return SCIP_OKAY;
18184 }
18185 
18186 /** adds coefficient to linear constraint (if it is not zero) */
18188  SCIP* scip, /**< SCIP data structure */
18189  SCIP_CONS* cons, /**< constraint data */
18190  SCIP_VAR* var, /**< variable of constraint entry */
18191  SCIP_Real val /**< coefficient of constraint entry */
18192  )
18193 {
18194  assert(scip != NULL);
18195  assert(cons != NULL);
18196  assert(var != NULL);
18197 
18198  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18199  {
18200  SCIPerrorMessage("constraint is not linear\n");
18201  return SCIP_INVALIDDATA;
18202  }
18203 
18204  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18205  * constraint after presolving we have to ensure that it holds active variables
18206  */
18207  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18208  {
18209  SCIP_CONSDATA* consdata;
18210  SCIP_VAR** consvars;
18211  SCIP_Real* consvals;
18212  SCIP_Real constant = 0.0;
18213  SCIP_Real rhs;
18214  SCIP_Real lhs;
18215  int nconsvars;
18216  int requiredsize;
18217  int v;
18218 
18219  nconsvars = 1;
18220  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18221  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18222  consvars[0] = var;
18223  consvals[0] = val;
18224 
18225  /* get active variables for new constraint */
18226  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18227 
18228  /* if space was not enough we need to resize the buffers */
18229  if( requiredsize > nconsvars )
18230  {
18231  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18232  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18233 
18234  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18235  assert(requiredsize <= nconsvars);
18236  }
18237 
18238  consdata = SCIPconsGetData(cons);
18239  assert(consdata != NULL);
18240 
18241  lhs = consdata->lhs;
18242  rhs = consdata->rhs;
18243 
18244  /* adjust sides and check that we do not subtract infinity values */
18245  /* constant is infinite */
18246  if( SCIPisInfinity(scip, REALABS(constant)) )
18247  {
18248  if( constant < 0.0 )
18249  {
18250  if( SCIPisInfinity(scip, lhs) )
18251  {
18252  SCIPfreeBufferArray(scip, &consvals);
18253  SCIPfreeBufferArray(scip, &consvars);
18254 
18255  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));
18256 
18257  SCIPABORT();
18258  return SCIP_INVALIDDATA; /*lint !e527*/
18259  }
18260  if( SCIPisInfinity(scip, rhs) )
18261  {
18262  SCIPfreeBufferArray(scip, &consvals);
18263  SCIPfreeBufferArray(scip, &consvars);
18264 
18265  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));
18266 
18267  SCIPABORT();
18268  return SCIP_INVALIDDATA; /*lint !e527*/
18269  }
18270 
18271  lhs = -SCIPinfinity(scip);
18272  rhs = -SCIPinfinity(scip);
18273  }
18274  else
18275  {
18276  if( SCIPisInfinity(scip, -lhs) )
18277  {
18278  SCIPfreeBufferArray(scip, &consvals);
18279  SCIPfreeBufferArray(scip, &consvars);
18280 
18281  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));
18282 
18283  SCIPABORT();
18284  return SCIP_INVALIDDATA; /*lint !e527*/
18285  }
18286  if( SCIPisInfinity(scip, -rhs) )
18287  {
18288  SCIPfreeBufferArray(scip, &consvals);
18289  SCIPfreeBufferArray(scip, &consvars);
18290 
18291  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));
18292 
18293  SCIPABORT();
18294  return SCIP_INVALIDDATA; /*lint !e527*/
18295  }
18296 
18297  lhs = SCIPinfinity(scip);
18298  rhs = SCIPinfinity(scip);
18299  }
18300  }
18301  /* constant is not infinite */
18302  else
18303  {
18304  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18305  lhs -= constant;
18306  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18307  rhs -= constant;
18308 
18309  if( SCIPisInfinity(scip, -lhs) )
18310  lhs = -SCIPinfinity(scip);
18311  else if( SCIPisInfinity(scip, lhs) )
18312  lhs = SCIPinfinity(scip);
18313 
18314  if( SCIPisInfinity(scip, rhs) )
18315  rhs = SCIPinfinity(scip);
18316  else if( SCIPisInfinity(scip, -rhs) )
18317  rhs = -SCIPinfinity(scip);
18318  }
18319 
18320  /* add all active variables to constraint */
18321  for( v = nconsvars - 1; v >= 0; --v )
18322  {
18323  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18324  }
18325 
18326  /* update left and right hand sides */
18327  SCIP_CALL( chgLhs(scip, cons, lhs));
18328  SCIP_CALL( chgRhs(scip, cons, rhs));
18329 
18330  SCIPfreeBufferArray(scip, &consvals);
18331  SCIPfreeBufferArray(scip, &consvars);
18332  }
18333  else
18334  {
18335  SCIP_CALL( addCoef(scip, cons, var, val) );
18336  }
18337 
18338  return SCIP_OKAY;
18339 }
18340 
18341 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18342  * not yet contained in the constraint
18343  *
18344  * @note This method may only be called during problem creation stage for an original constraint and variable.
18345  *
18346  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18347  */
18349  SCIP* scip, /**< SCIP data structure */
18350  SCIP_CONS* cons, /**< constraint data */
18351  SCIP_VAR* var, /**< variable of constraint entry */
18352  SCIP_Real val /**< new coefficient of constraint entry */
18353  )
18354 {
18355  SCIP_CONSDATA* consdata;
18356  SCIP_VAR** vars;
18357  SCIP_Bool found;
18358  int i;
18359 
18360  assert(scip != NULL);
18361  assert(cons != NULL);
18362  assert(var != NULL);
18363 
18364  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18365  {
18366  SCIPerrorMessage("constraint is not linear\n");
18368  }
18369 
18370  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18371  {
18372  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18373  return SCIP_INVALIDDATA;
18374  }
18375 
18376  consdata = SCIPconsGetData(cons);
18377  assert(consdata != NULL);
18378 
18379  vars = consdata->vars;
18380  found = FALSE;
18381  i = 0;
18382  while( i < consdata->nvars )
18383  {
18384  if( vars[i] == var )
18385  {
18386  if( found || SCIPisZero(scip, val) )
18387  {
18388  SCIP_CALL( delCoefPos(scip, cons, i) );
18389 
18390  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18391  i--;
18392  }
18393  else
18394  {
18395  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18396  }
18397  found = TRUE;
18398  }
18399  i++;
18400  }
18401 
18402  if( !found && !SCIPisZero(scip, val) )
18403  {
18404  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18405  }
18406 
18407  return SCIP_OKAY;
18408 }
18409 
18410 /** deletes variable from linear constraint
18411  *
18412  * @note This method may only be called during problem creation stage for an original constraint and variable.
18413  *
18414  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18415  */
18417  SCIP* scip, /**< SCIP data structure */
18418  SCIP_CONS* cons, /**< constraint data */
18419  SCIP_VAR* var /**< variable of constraint entry */
18420  )
18421 {
18422  assert(scip != NULL);
18423  assert(cons != NULL);
18424  assert(var != NULL);
18425 
18426  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18427 
18428  return SCIP_OKAY;
18429 }
18430 
18431 /** gets left hand side of linear constraint */
18433  SCIP* scip, /**< SCIP data structure */
18434  SCIP_CONS* cons /**< constraint data */
18435  )
18436 {
18437  SCIP_CONSDATA* consdata;
18438 
18439  assert(scip != NULL);
18440  assert(cons != NULL);
18441 
18442  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18443  {
18444  SCIPerrorMessage("constraint is not linear\n");
18445  SCIPABORT();
18446  return SCIP_INVALID; /*lint !e527*/
18447  }
18448 
18449  consdata = SCIPconsGetData(cons);
18450  assert(consdata != NULL);
18452  return consdata->lhs;
18453 }
18454 
18455 /** gets right hand side of linear constraint */
18457  SCIP* scip, /**< SCIP data structure */
18458  SCIP_CONS* cons /**< constraint data */
18459  )
18460 {
18461  SCIP_CONSDATA* consdata;
18462 
18463  assert(scip != NULL);
18464  assert(cons != NULL);
18465 
18466  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18467  {
18468  SCIPerrorMessage("constraint is not linear\n");
18469  SCIPABORT();
18470  return SCIP_INVALID; /*lint !e527*/
18471  }
18472 
18473  consdata = SCIPconsGetData(cons);
18474  assert(consdata != NULL);
18476  return consdata->rhs;
18477 }
18478 
18479 /** changes left hand side of linear constraint */
18481  SCIP* scip, /**< SCIP data structure */
18482  SCIP_CONS* cons, /**< constraint data */
18483  SCIP_Real lhs /**< new left hand side */
18484  )
18485 {
18486  assert(scip != NULL);
18487  assert(cons != NULL);
18488 
18489  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18490  {
18491  SCIPerrorMessage("constraint is not linear\n");
18492  return SCIP_INVALIDDATA;
18493  }
18494 
18495  SCIP_CALL( chgLhs(scip, cons, lhs) );
18496 
18497  return SCIP_OKAY;
18498 }
18500 /** changes right hand side of linear constraint */
18502  SCIP* scip, /**< SCIP data structure */
18503  SCIP_CONS* cons, /**< constraint data */
18504  SCIP_Real rhs /**< new right hand side */
18505  )
18506 {
18507  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18508  {
18509  SCIPerrorMessage("constraint is not linear\n");
18510  return SCIP_INVALIDDATA;
18511  }
18512 
18513  SCIP_CALL( chgRhs(scip, cons, rhs) );
18514 
18515  return SCIP_OKAY;
18516 }
18517 
18518 /** gets the number of variables in the linear constraint */
18519 int SCIPgetNVarsLinear(
18520  SCIP* scip, /**< SCIP data structure */
18521  SCIP_CONS* cons /**< constraint data */
18522  )
18523 {
18524  SCIP_CONSDATA* consdata;
18525 
18526  assert(scip != NULL);
18527  assert(cons != NULL);
18528 
18529  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18530  {
18531  SCIPerrorMessage("constraint is not linear\n");
18532  SCIPABORT();
18533  return -1; /*lint !e527*/
18534  }
18535 
18536  consdata = SCIPconsGetData(cons);
18537  assert(consdata != NULL);
18539  return consdata->nvars;
18540 }
18541 
18542 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18544  SCIP* scip, /**< SCIP data structure */
18545  SCIP_CONS* cons /**< constraint data */
18546  )
18547 {
18548  SCIP_CONSDATA* consdata;
18549 
18550  assert(scip != NULL);
18551  assert(cons != NULL);
18552 
18553  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18554  {
18555  SCIPerrorMessage("constraint is not linear\n");
18556  SCIPABORT();
18557  return NULL; /*lint !e527*/
18558  }
18559 
18560  consdata = SCIPconsGetData(cons);
18561  assert(consdata != NULL);
18563  return consdata->vars;
18564 }
18565 
18566 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18568  SCIP* scip, /**< SCIP data structure */
18569  SCIP_CONS* cons /**< constraint data */
18570  )
18571 {
18572  SCIP_CONSDATA* consdata;
18573 
18574  assert(scip != NULL);
18575  assert(cons != NULL);
18576 
18577  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18578  {
18579  SCIPerrorMessage("constraint is not linear\n");
18580  SCIPABORT();
18581  return NULL; /*lint !e527*/
18582  }
18583 
18584  consdata = SCIPconsGetData(cons);
18585  assert(consdata != NULL);
18587  return consdata->vals;
18588 }
18589 
18590 /** gets the activity of the linear constraint in the given solution
18591  *
18592  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18593  * comprises positive and negative infinity contributions
18594  */
18596  SCIP* scip, /**< SCIP data structure */
18597  SCIP_CONS* cons, /**< constraint data */
18598  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18599  )
18600 {
18601  SCIP_CONSDATA* consdata;
18602 
18603  assert(scip != NULL);
18604  assert(cons != NULL);
18605 
18606  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18607  {
18608  SCIPerrorMessage("constraint is not linear\n");
18609  SCIPABORT();
18610  return SCIP_INVALID; /*lint !e527*/
18611  }
18612 
18613  consdata = SCIPconsGetData(cons);
18614  assert(consdata != NULL);
18615 
18616  if( consdata->row != NULL )
18617  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18618  else
18619  return consdataGetActivity(scip, consdata, sol);
18620 }
18621 
18622 /** gets the feasibility of the linear constraint in the given solution */
18624  SCIP* scip, /**< SCIP data structure */
18625  SCIP_CONS* cons, /**< constraint data */
18626  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18627  )
18628 {
18629  SCIP_CONSDATA* consdata;
18630 
18631  assert(scip != NULL);
18632  assert(cons != NULL);
18633 
18634  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18635  {
18636  SCIPerrorMessage("constraint is not linear\n");
18637  SCIPABORT();
18638  return SCIP_INVALID; /*lint !e527*/
18639  }
18640 
18641  consdata = SCIPconsGetData(cons);
18642  assert(consdata != NULL);
18643 
18644  if( consdata->row != NULL )
18645  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18646  else
18647  return consdataGetFeasibility(scip, consdata, sol);
18648 }
18649 
18650 /** gets the dual solution of the linear constraint in the current LP */
18652  SCIP* scip, /**< SCIP data structure */
18653  SCIP_CONS* cons /**< constraint data */
18654  )
18655 {
18656  SCIP_CONSDATA* consdata;
18657 
18658  assert(scip != NULL);
18659  assert(cons != NULL);
18660  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18661 
18662  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18663  {
18664  SCIPerrorMessage("constraint is not linear\n");
18665  SCIPABORT();
18666  return SCIP_INVALID; /*lint !e527*/
18667  }
18668 
18669  consdata = SCIPconsGetData(cons);
18670  assert(consdata != NULL);
18671 
18672  if( consdata->row != NULL )
18673  return SCIProwGetDualsol(consdata->row);
18674  else
18675  return 0.0;
18676 }
18677 
18678 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18680  SCIP* scip, /**< SCIP data structure */
18681  SCIP_CONS* cons /**< constraint data */
18682  )
18683 {
18684  SCIP_CONSDATA* consdata;
18685 
18686  assert(scip != NULL);
18687  assert(cons != NULL);
18688  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18689 
18690  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18691  {
18692  SCIPerrorMessage("constraint is not linear\n");
18693  SCIPABORT();
18694  return SCIP_INVALID; /*lint !e527*/
18695  }
18696 
18697  consdata = SCIPconsGetData(cons);
18698  assert(consdata != NULL);
18699 
18700  if( consdata->row != NULL )
18701  return SCIProwGetDualfarkas(consdata->row);
18702  else
18703  return 0.0;
18704 }
18705 
18706 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18707  * the user must not modify the row!
18708  */
18710  SCIP* scip, /**< SCIP data structure */
18711  SCIP_CONS* cons /**< constraint data */
18712  )
18713 {
18714  SCIP_CONSDATA* consdata;
18715 
18716  assert(scip != NULL);
18717  assert(cons != NULL);
18718 
18719  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18720  {
18721  SCIPerrorMessage("constraint is not linear\n");
18722  SCIPABORT();
18723  return NULL; /*lint !e527*/
18724  }
18725 
18726  consdata = SCIPconsGetData(cons);
18727  assert(consdata != NULL);
18729  return consdata->row;
18730 }
18731 
18732 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18734  SCIP* scip, /**< SCIP data structure */
18735  SCIP_CONS* cons, /**< source constraint to try to convert */
18736  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18737  )
18738 {
18739  SCIP_CONSHDLR* conshdlr;
18740  SCIP_CONSHDLRDATA* conshdlrdata;
18741  SCIP_CONSDATA* consdata;
18742  SCIP_VAR* var;
18743  SCIP_Real val;
18744  SCIP_Real lb;
18745  SCIP_Real ub;
18746  SCIP_Real poscoeffsum;
18747  SCIP_Real negcoeffsum;
18748  SCIP_Bool infeasible;
18749  SCIP_Bool integral;
18750  int nchgsides = 0;
18751  int nposbin;
18752  int nnegbin;
18753  int nposint;
18754  int nnegint;
18755  int nposimpl;
18756  int nnegimpl;
18757  int nposimplbin;
18758  int nnegimplbin;
18759  int nposcont;
18760  int nnegcont;
18761  int ncoeffspone;
18762  int ncoeffsnone;
18763  int ncoeffspint;
18764  int ncoeffsnint;
18765  int ncoeffspfrac;
18766  int ncoeffsnfrac;
18767  int i;
18768 
18769  assert(scip != NULL);
18770  assert(cons != NULL);
18771  assert(upgdcons != NULL);
18772 
18773  *upgdcons = NULL;
18774 
18775  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18776  if( SCIPconsIsModifiable(cons) )
18777  return SCIP_OKAY;
18778 
18779  /* check for upgradability */
18780  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18781  return SCIP_OKAY;
18782 
18783  /* get the constraint handler and check, if it's really a linear constraint */
18784  conshdlr = SCIPconsGetHdlr(cons);
18785  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18786  {
18787  SCIPerrorMessage("constraint is not linear\n");
18788  return SCIP_INVALIDDATA;
18789  }
18790 
18791  /* get constraint handler data and constraint data */
18792  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18793  assert(conshdlrdata != NULL);
18794  consdata = SCIPconsGetData(cons);
18795  assert(consdata != NULL);
18796 
18797  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18798  if( consdata->upgraded )
18799  return SCIP_OKAY;
18800 
18801  /* check, if the constraint is already stored as LP row */
18802  if( consdata->row != NULL )
18803  {
18804  if( SCIProwIsInLP(consdata->row) )
18805  {
18806  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18807  return SCIP_INVALIDDATA;
18808  }
18809  else
18810  {
18811  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18812  }
18813  }
18814 
18815  /* normalize constraint */
18816  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18817 
18818  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18819  * skipped and we hope that the infeasibility gets detected later again.
18820  *
18821  * TODO: do we want to try to upgrade the constraint anyway?
18822  *
18823  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18824  * proven to be infeasible.
18825  */
18826  if( infeasible ) /*lint !e774*/
18827  return SCIP_OKAY;
18828 
18829  /* tighten sides */
18830  SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18831 
18832  if( infeasible ) /*lint !e774*/
18833  return SCIP_OKAY;
18834 
18835  /*
18836  * calculate some statistics on linear constraint
18837  */
18838 
18839  nposbin = 0;
18840  nnegbin = 0;
18841  nposint = 0;
18842  nnegint = 0;
18843  nposimpl = 0;
18844  nnegimpl = 0;
18845  nposimplbin = 0;
18846  nnegimplbin = 0;
18847  nposcont = 0;
18848  nnegcont = 0;
18849  ncoeffspone = 0;
18850  ncoeffsnone = 0;
18851  ncoeffspint = 0;
18852  ncoeffsnint = 0;
18853  ncoeffspfrac = 0;
18854  ncoeffsnfrac = 0;
18855  integral = TRUE;
18856  poscoeffsum = 0.0;
18857  negcoeffsum = 0.0;
18858 
18859  for( i = 0; i < consdata->nvars; ++i )
18860  {
18861  var = consdata->vars[i];
18862  val = consdata->vals[i];
18863  lb = SCIPvarGetLbLocal(var);
18864  ub = SCIPvarGetUbLocal(var);
18865  assert(!SCIPisZero(scip, val));
18866 
18867  switch( SCIPvarGetType(var) )
18868  {
18869  case SCIP_VARTYPE_BINARY:
18870  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18871  integral = integral && SCIPisIntegral(scip, val);
18872  if( val >= 0.0 )
18873  nposbin++;
18874  else
18875  nnegbin++;
18876  break;
18877  case SCIP_VARTYPE_INTEGER:
18878  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18879  integral = integral && SCIPisIntegral(scip, val);
18880  if( val >= 0.0 )
18881  nposint++;
18882  else
18883  nnegint++;
18884  break;
18885  case SCIP_VARTYPE_IMPLINT:
18886  if( SCIPvarIsBinary(var) )
18887  {
18888  if( val >= 0.0 )
18889  nposimplbin++;
18890  else
18891  nnegimplbin++;
18892  }
18893  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18894  integral = integral && SCIPisIntegral(scip, val);
18895  if( val >= 0.0 )
18896  nposimpl++;
18897  else
18898  nnegimpl++;
18899  break;
18901  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18902  if( val >= 0.0 )
18903  nposcont++;
18904  else
18905  nnegcont++;
18906  break;
18907  default:
18908  SCIPerrorMessage("unknown variable type\n");
18909  return SCIP_INVALIDDATA;
18910  }
18911  if( SCIPisEQ(scip, val, 1.0) )
18912  ncoeffspone++;
18913  else if( SCIPisEQ(scip, val, -1.0) )
18914  ncoeffsnone++;
18915  else if( SCIPisIntegral(scip, val) )
18916  {
18917  if( SCIPisPositive(scip, val) )
18918  ncoeffspint++;
18919  else
18920  ncoeffsnint++;
18921  }
18922  else
18923  {
18924  if( SCIPisPositive(scip, val) )
18925  ncoeffspfrac++;
18926  else
18927  ncoeffsnfrac++;
18928  }
18929  if( SCIPisPositive(scip, val) )
18930  poscoeffsum += val;
18931  else
18932  negcoeffsum += val;
18933  }
18934 
18935  /*
18936  * call the upgrading methods
18937  */
18938 
18939  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18940  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18941  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",
18942  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18943  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18944  poscoeffsum, negcoeffsum, integral);
18945 
18946  /* try all upgrading methods in priority order in case the upgrading step is enable */
18947  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18948  {
18949  if( conshdlrdata->linconsupgrades[i]->active )
18950  {
18951  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18952  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18953  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18954  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18955  poscoeffsum, negcoeffsum, integral,
18956  upgdcons) );
18957  }
18958  }
18959 
18960 #ifdef SCIP_DEBUG
18961  if( *upgdcons != NULL )
18962  {
18963  SCIPdebugPrintCons(scip, cons, NULL);
18964  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18965  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18966  }
18967 #endif
18968 
18969  return SCIP_OKAY; /*lint !e438*/
18970 }
18971 
18972 /** cleans up (multi-)aggregations and fixings from linear constraints */
18974  SCIP* scip, /**< SCIP data structure */
18975  SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18976  SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18977  )
18978 {
18979  SCIP_CONSHDLR* conshdlr;
18980  SCIP_CONS** conss;
18981  int nconss;
18982  int i;
18983 
18984  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18985  if( conshdlr == NULL )
18986  return SCIP_OKAY;
18987 
18988  assert(infeasible != NULL);
18989  *infeasible = FALSE;
18990 
18991  nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18992  conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18993 
18994  for( i = 0; i < nconss; ++i )
18995  {
18996  SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18997 
18998  if( *infeasible )
18999  break;
19000  }
19001 
19002  return SCIP_OKAY;
19003 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
#define EVENTHDLR_DESC
Definition: cons_linear.c:113
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:105
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:120
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4212
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1730
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1693
enum SCIP_LinConstype SCIP_LINCONSTYPE
Definition: type_cons.h:90
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:572
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6835
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1462
static SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
Definition: cons_linear.c:871
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:422
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:735
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:4037
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10777
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5203
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3179
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2128
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:3296
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:136
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:365
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:124
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8349
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17693
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:595
SCIP_RETCODE SCIPincludeConsUpgradeNonlinear(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nlconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_NAME
Definition: cons_linear.c:94
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1992
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:104
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:3200
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2497
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:1629
public methods for memory management
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:171
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1567
#define MAXSCALEDCOEF
Definition: cons_linear.c:181
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:354
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:886
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:133
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3801
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7906
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18503
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:120
#define DEFAULT_SORTVARS
Definition: cons_linear.c:130
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9566
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:5445
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17901
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:825
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
#define SCIP_MAXSTRLEN
Definition: def.h:302
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3354
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17443
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:317
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1758
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:840
void SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS *linconsstats, SCIP_LINCONSTYPE linconstype, int increment)
Definition: cons.c:7984
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17681
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip_cons.c:1317
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:2091
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17957
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1181
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:687
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition: event.c:1283
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:104
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2320
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:525
SCIP_Real SCIPgetRhsNonlinear(SCIP_CONS *cons)
static SCIP_DECL_CONSINITSOL(consInitsolLinear)
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:122
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1439
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1470
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1248
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17422
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1330
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4268
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:165
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip_copy.c:2068
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define NLOCKTYPES
Definition: type_var.h:94
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:2897
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3354
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4554
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:148
#define FALSE
Definition: def.h:96
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4645
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1231
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8100
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11096
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:175
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10788
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:2959
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:606
#define TRUE
Definition: def.h:95
#define SCIPdebug(x)
Definition: pub_message.h:93
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:142
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1988
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:3585
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17738
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:126
#define SCIPstatisticMessage
Definition: pub_message.h:123
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:8369
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:54
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:7668
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:57
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:17591
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
void SCIPlinConsStatsReset(SCIP_LINCONSSTATS *linconsstats)
Definition: cons.c:7952
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17645
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8399
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:5320
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPdebugMessage
Definition: pub_message.h:96
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:127
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:229
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9735
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8449
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3088
enum Proprule PROPRULE
Definition: cons_linear.c:372
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:136
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:431
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5850
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4613
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17453
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:575
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:428
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:774
public methods for SCIP variables
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:756
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1562
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17727
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8359
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:125
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3245
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:618
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17312
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
#define SCIPdebugMsg
Definition: scip_message.h:78
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:83
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2336
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1480
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:802
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:145
SCIP_VAR ** x
Definition: circlepacking.c:63
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8151
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides, SCIP_Bool *infeasible)
Definition: cons_linear.c:9010
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:208
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:123
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:5114
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:943
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:704
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:109
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:110
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:2246
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8389
public functions to work with algebraic expressions
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:121
public methods for querying solving statistics
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:99
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17717
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17523
#define MAXCONSPRESOLROUNDS
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4259
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:9305
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:546
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip_cons.c:1242
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip_var.c:8176
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5323
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:7285
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:6921
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3811
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17911
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:438
SCIP_VAR * w
Definition: circlepacking.c:67
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:115
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:8535
public methods for managing constraints
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:155
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1242
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip_general.c:612
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1872
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8429
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:117
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:341
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, SCIP_Bool *infeasible)
SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
Definition: expr_sum.c:1166
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:5375
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:2517
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:100
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIPerrorMessage
Definition: pub_message.h:64
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4182
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1266
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:100
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3393
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:363
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8598
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3474
public methods for event handler plugins and event handlers
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5432
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition: expr_var.c:416
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1025
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1794
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1438
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:6780
static INLINE uint32_t SCIPrealHashCode(double x)
Definition: pub_misc.h:544
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:173
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3623
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:465
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2164
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3430
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4437
SCIP_RETCODE SCIPsetConsChecked(SCIP *scip, SCIP_CONS *cons, SCIP_Bool check)
Definition: scip_cons.c:1292
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2114
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:413
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:9132
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8090
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17657
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8309
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17242
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:366
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4202
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5179
#define NULL
Definition: lpi_spx1.cpp:164
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1960
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3916
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:5230
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:450
#define SCIPhashSeven(a, b, c, d, e, f, g)
Definition: pub_misc.h:535
#define REALABS(x)
Definition: def.h:210
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
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:636
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:106
public methods for problem copies
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8439
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5101
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1443
#define SCIP_CALL(x)
Definition: def.h:394
SCIP_Real SCIPgetLowerbound(SCIP *scip)
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
Definition: cons_linear.c:2616
enum Proprule PROPRULE
Definition: cons_and.c:177
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:98
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5515
#define SCIPhashSignature64(a)
Definition: pub_misc.h:517
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:1738
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17705
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17529
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2627
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:285
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:2416
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:225
static SCIP_Bool isFiniteNonnegativeIntegral(SCIP *scip, SCIP_Real x)
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8329
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:4116
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:641
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:299
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
static SCIP_DECL_CONSTRANS(consTransLinear)
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17411
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:122
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4597
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:7758
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:2221
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:160
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:4513
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1120
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17371
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2754
static SCIP_RETCODE retrieveParallelConstraints(SCIP_HASHTABLE *hashtable, SCIP_CONS **querycons, SCIP_CONS **parallelconss, int *nparallelconss)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3497
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1053
#define SCIP_Bool
Definition: def.h:93
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip_lp.c:1607
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:107
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:101
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4209
static const char * paramname[]
Definition: lpi_msk.c:5096
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1411
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3111
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:7103
constraint handler for nonlinear constraints specified by algebraic expressions
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:584
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:152
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2482
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:150
#define MAX(x, y)
Definition: tclique_def.h:92
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4601
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
Definition: cons_linear.c:7569
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8110
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11932
methods for debugging
public methods for LP management
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8219
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2529
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:1583
public methods for cuts and aggregation rows
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8289
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2068
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8259
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17749
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1277
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:400
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18493
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2354
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:197
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17633
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:114
static int getVarWeight(SCIP_VAR *var)
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:921
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8276
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:136
int SCIPgetNRuns(SCIP *scip)
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17325
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4351
#define MAXDNOM
Definition: cons_linear.c:180
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:779
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2558
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17669
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:2144
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:121
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:120
static void findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12764
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:5501
SCIP_RETCODE SCIPclassifyConstraintTypesLinear(SCIP *scip, SCIP_LINCONSSTATS *linconsstats)
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:119
#define SCIP_MAXTREEDEPTH
Definition: def.h:330
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4631
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
public methods for the LP relaxation, rows and columns
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:149
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7545
#define MINVALRECOMP
Definition: cons_linear.c:194
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2296
#define QUAD_ASSIGN_Q(a, b)
Definition: dbldblarith.h:52
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:96
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8541
#define SCIP_REAL_MAX
Definition: def.h:187
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:391
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2665
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1357
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:343
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:3696
static SCIP_Bool canTightenBounds(SCIP_CONS *cons)
Definition: cons_linear.c:5347
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:182
static SCIP_DECL_CONSACTIVE(consActiveLinear)
methods for sorting joint arrays of various types
static SCIP_DECL_CONSCHECK(consCheckLinear)
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8483
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:510
#define EPSGT(x, y, eps)
Definition: def.h:214
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:560
public methods for branching rule plugins and branching
SCIP_VAR ** b
Definition: circlepacking.c:65
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3225
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
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:5792
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:668
general public methods
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5450
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:2746
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
public methods for solutions
static const SCIP_Real scalars[]
Definition: lp.c:5743
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:711
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1668
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8120
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:5615
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:390
#define CONTWEIGHT
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4574
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:1267
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1491
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:808
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:414
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
public methods for conflict analysis handlers
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3042
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:8041
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:660
public methods for the probing mode
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1119
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:772
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:534
public methods for message output
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1218
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1421
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9622
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:116
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17361
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:8401
#define DEFAULT_MAXDUALMULTAGGRQUOT
Definition: cons_linear.c:177
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1214
#define SCIP_Real
Definition: def.h:186
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7107
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8339
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_lp.c:1727
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:703
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:73
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9680
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:151
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:848
#define EVENTHDLR_NAME
Definition: cons_linear.c:112
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:97
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:4672
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4617
public methods for message handling
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, FILE *file)
Definition: cons_linear.c:1159
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8279
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip_var.c:8565
static unsigned int getParallelConsKey(SCIP_CONS *cons)
#define SCIP_INVALID
Definition: def.h:206
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:168
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8269
Proprule
Definition: cons_and.c:169
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3751
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:95
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
#define SCIP_Longint
Definition: def.h:171
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18013
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17581
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:490
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:298
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17407
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7974
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1384
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:73
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9734
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17967
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17384
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:404
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8299
static SCIP_Bool isRangedRow(SCIP *scip, SCIP_Real lhs, SCIP_Real rhs)
#define MAXVALRECOMP
Definition: cons_linear.c:193
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:701
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:132
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:664
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:139
#define QUAD_MEMBER(x)
Definition: dbldblarith.h:48
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:439
#define DEFAULT_EXTRACTCLIQUES
Definition: cons_linear.c:178
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3228
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:373
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:170
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:462
#define SCIPABORT()
Definition: def.h:366
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:230
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17433
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9032
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1361
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17463
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:391
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1268
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define MAXACTVAL
Definition: cons_linear.c:187
#define INTWEIGHT
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:8629
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:139
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4932
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9284
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7632
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:71
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:2018
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
#define DEFAULT_MAXMULTAGGRQUOT
Definition: cons_linear.c:176
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:57
int SCIPgetNSepaRounds(SCIP *scip)
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:125
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17571
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17397
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:2043
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1079
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:275
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip_cons.c:1217
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:124
memory allocation routines
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:169