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 and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11424  * common divisor
11425  *
11426  * 1. lhs <= a^Tx <= rhs, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs then we can change this
11427  * constraint to 1^Tx = 1
11428  */
11429 static
11431  SCIP* scip, /**< SCIP data structure */
11432  SCIP_CONS* cons, /**< linear constraint */
11433  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11434  int* nchgsides /**< pointer to store the amount of changed sides */
11435  )
11436 {
11437  SCIP_CONSDATA* consdata;
11438  SCIP_VAR** vars;
11439  SCIP_Real* vals;
11440  SCIP_Real minval;
11441  SCIP_Real secondminval;
11442  SCIP_Real maxval;
11443  SCIP_Real lhs;
11444  SCIP_Real rhs;
11445  int nvars;
11446  int v;
11447 
11448  /* we must not change a modifiable constraint in any way */
11450  return SCIP_OKAY;
11451 
11452  if( SCIPconsIsDeleted(cons) )
11453  return SCIP_OKAY;
11454 
11455  consdata = SCIPconsGetData(cons);
11456  assert(consdata != NULL);
11457 
11458  nvars = consdata->nvars;
11459 
11460  /* do not check empty or bound-constraints */
11461  if( nvars < 2 )
11462  return SCIP_OKAY;
11463 
11464  vals = consdata->vals;
11465  vars = consdata->vars;
11466  assert(vars != NULL);
11467  assert(vals != NULL);
11468 
11469  lhs = consdata->lhs;
11470  rhs = consdata->rhs;
11471  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11472  assert(!SCIPisNegative(scip, rhs));
11473 
11474  minval = SCIP_INVALID;
11475  secondminval = SCIP_INVALID;
11476  maxval = -SCIP_INVALID;
11477 
11478  for( v = nvars - 1; v >= 0; --v )
11479  {
11480  if( SCIPvarIsBinary(vars[v]) )
11481  {
11482  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11483  {
11484  secondminval = minval;
11485  minval = vals[v];
11486  }
11487  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11488  secondminval = vals[v];
11489 
11490  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11491  maxval = vals[v];
11492  }
11493  else
11494  break;
11495  }
11496 
11497  /* check if all variables are binary */
11498  if( v == -1 )
11499  {
11500  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11501  return SCIP_OKAY;
11502 
11503  /* check if we can and need to choose exactly one binary variable */
11504  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11505  {
11506  /* change all coefficients to 1.0 */
11507  for( v = nvars - 1; v >= 0; --v )
11508  {
11509  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11510  }
11511  (*nchgcoefs) += nvars;
11512 
11513  /* replace old right and left hand side with 1.0 */
11514  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11515  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11516  (*nchgsides) += 2;
11517  }
11518  }
11519 
11520  return SCIP_OKAY;
11521 }
11522 
11523 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11524  * for equations @see rangedRowSimplify() will be called
11525  *
11526  * there are several different coefficient reduction steps which will be applied
11527  *
11528  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11529  *
11530  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11531  *
11532  * 2. We try to remove redundant fractional parts in a constraint
11533  *
11534  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11535  *
11536  * 3. We are using the greatest common divisor for further reductions
11537  *
11538  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11539  * integral
11540  */
11541 static
11543  SCIP* scip, /**< SCIP data structure */
11544  SCIP_CONS* cons, /**< linear constraint */
11545  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11546  int* nchgsides, /**< pointer to store the amount of changed sides */
11547  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
11548  )
11549 {
11550  SCIP_CONSDATA* consdata;
11551  SCIP_VAR** vars;
11552  SCIP_Real* vals;
11553  int* perm;
11554  SCIP_Real minactsub;
11555  SCIP_Real maxactsub;
11556  SCIP_Real siderest;
11557  SCIP_Real feastol;
11558  SCIP_Real newcoef;
11559  SCIP_Real absval;
11560  SCIP_Real minact;
11561  SCIP_Real maxact;
11562  SCIP_Real side;
11563  SCIP_Real lhs;
11564  SCIP_Real rhs;
11565  SCIP_Real lb;
11566  SCIP_Real ub;
11567  SCIP_Longint restcoef;
11568  SCIP_Longint oldgcd;
11569  SCIP_Longint rest;
11570  SCIP_Longint gcd;
11571  SCIP_Bool isminsettoinfinity;
11572  SCIP_Bool ismaxsettoinfinity;
11573  SCIP_Bool isminrelax;
11574  SCIP_Bool ismaxrelax;
11575  SCIP_Bool allcoefintegral;
11576  SCIP_Bool onlybin;
11577  SCIP_Bool hasrhs;
11578  SCIP_Bool haslhs;
11579  int oldnchgcoefs;
11580  int oldnchgsides;
11581  int foundbin;
11582  int candpos;
11583  int candpos2;
11584  int offsetv;
11585  int nvars;
11586  int v;
11587  int w;
11588 
11589  assert(scip != NULL);
11590  assert(cons != NULL);
11591  assert(nchgcoefs != NULL);
11592  assert(nchgsides != NULL);
11593 
11594  *infeasible = FALSE;
11595 
11596  /* we must not change a modifiable constraint in any way */
11597  if( SCIPconsIsModifiable(cons) )
11598  return SCIP_OKAY;
11599 
11600  if( SCIPconsIsDeleted(cons) )
11601  return SCIP_OKAY;
11602 
11603  consdata = SCIPconsGetData(cons);
11604  assert(consdata != NULL);
11605 
11606  nvars = consdata->nvars;
11607 
11608  /* do not check empty or bound-constraints */
11609  if( nvars <= 2 )
11610  return SCIP_OKAY;
11611 
11612  /* update maximal activity delta if necessary */
11613  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11614  consdataRecomputeMaxActivityDelta(scip, consdata);
11615 
11616  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11617  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11618  checkMaxActivityDelta(scip, consdata);
11619 
11620  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11621  * accordingly
11622  */
11623  /* can only work with valid non-infinity activities per variable */
11624  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11625  return SCIP_OKAY;
11626 
11627  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11628  * but the eventsystem seems to be full
11629  */
11630  consdata->normalized = FALSE;
11631 
11632  /* normalize constraint */
11633  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11634  assert(nvars == consdata->nvars);
11635 
11636  if( *infeasible )
11637  return SCIP_OKAY;
11638 
11639  if( !consdata->normalized )
11640  return SCIP_OKAY;
11641 
11642  lhs = consdata->lhs;
11643  rhs = consdata->rhs;
11644  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11645  assert(!SCIPisNegative(scip, rhs));
11646 
11647  if( !SCIPisInfinity(scip, -lhs) )
11648  haslhs = TRUE;
11649  else
11650  haslhs = FALSE;
11651 
11652  if( !SCIPisInfinity(scip, rhs) )
11653  hasrhs = TRUE;
11654  else
11655  hasrhs = FALSE;
11656 
11657  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11658  SCIPdebug( oldnchgsides = *nchgsides; )
11659 
11660  /* @todo also work on ranged rows */
11661  if( haslhs && hasrhs )
11662  {
11663  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11664 
11665  return SCIP_OKAY;
11666  }
11667  assert(haslhs != hasrhs);
11668 
11669  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11670  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11671  assert(!haslhs || !SCIPisNegative(scip, lhs));
11672 
11673  /* get temporary memory to store the sorted permutation */
11674  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11675 
11676  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11677  * value of their coefficients
11678  */
11679  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11680 
11681  /* perform sorting after permutation array */
11682  permSortConsdata(consdata, perm, nvars);
11683  consdata->indexsorted = FALSE;
11684  consdata->coefsorted = FALSE;
11685 
11686  vars = consdata->vars;
11687  vals = consdata->vals;
11688  assert(vars != NULL);
11689  assert(vals != NULL);
11690  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11691 
11692  /* free temporary memory */
11693  SCIPfreeBufferArray(scip, &perm);
11694 
11695  /* only check constraints with at least two non continuous variables */
11696  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11697  return SCIP_OKAY;
11698 
11699  /* do not process constraints when all coefficients are 1.0 */
11700  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11701  return SCIP_OKAY;
11702 
11703  feastol = SCIPfeastol(scip);
11704 
11705  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11706  SCIPdebugPrintCons(scip, cons, NULL);
11707 
11708  /* get global activities */
11709  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact,
11710  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11711 
11712  /* cannot work with infinite activities */
11713  if( isminsettoinfinity || ismaxsettoinfinity )
11714  return SCIP_OKAY;
11715 
11716  assert(!isminrelax);
11717  assert(!ismaxrelax);
11718  assert(maxact > minact);
11719  assert(!SCIPisInfinity(scip, -minact));
11720  assert(!SCIPisInfinity(scip, maxact));
11721 
11722  v = 0;
11723  offsetv = -1;
11724  side = haslhs ? lhs : rhs;
11725  minactsub = minact;
11726  maxactsub = maxact;
11727 
11728  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11729  * do not need to look at the large coefficients
11730  *
11731  * e.g. all x are binary, z are positive integer
11732  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11733  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11734  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11735  *
11736  * can be changed to
11737  *
11738  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11739  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11740  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11741  */
11742 
11743  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11744  * hand side, we cannot apply the extra reduction step and need to reset v
11745  *
11746  * 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
11747  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11748  * for all i is a solution
11749  *
11750  * also redundancy of variables would not be correctly determined in such a case
11751  */
11752  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11753  {
11754  v = 1;
11755 
11756  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11757  {
11758  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11759  * extra step, which might have worked
11760  */
11761  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11762  {
11763  v = 0;
11764  break;
11765  }
11766 
11767  ++v;
11768  }
11769 
11770  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11771  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11772  if( v == nvars )
11773  return SCIP_OKAY;
11774 
11775  /* cannot work with continuous variables which have a big coefficient */
11776  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11777  return SCIP_OKAY;
11778 
11779  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11780  if( SCIPisEQ(scip, side, -vals[v]) )
11781  v = 0;
11782 
11783  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11784  * reduction
11785  */
11786  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11787  v = 0;
11788 
11789  if( v > 0 )
11790  {
11791  assert(v < nvars);
11792 
11793  offsetv = v - 1;
11794 
11795  for( w = 0; w < v; ++w )
11796  {
11797  lb = SCIPvarGetLbGlobal(vars[w]);
11798  ub = SCIPvarGetUbGlobal(vars[w]);
11799 
11800  assert(vals[w] > 0);
11801 
11802  /* update residual activities */
11803  maxactsub -= ub * vals[w];
11804  minactsub -= lb * vals[w];
11805  assert(maxactsub > minactsub);
11806  }
11807  }
11808  }
11809 
11810  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11811  *
11812  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11813  *
11814  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11815  * to
11816  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11817  */
11818  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11819  {
11820  SCIP_Bool redundant = FALSE;
11821  SCIP_Bool numericsok;
11822  SCIP_Bool rredundant;
11823  SCIP_Bool lredundant;
11824 
11825 
11826  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11827  assert(gcd >= 1);
11828 
11829  if( v == 0 )
11830  {
11831  lb = SCIPvarGetLbGlobal(vars[0]);
11832  ub = SCIPvarGetUbGlobal(vars[0]);
11833 
11834  /* update residual activities */
11835  if( vals[0] > 0 )
11836  {
11837  maxactsub -= ub * vals[0];
11838  minactsub -= lb * vals[0];
11839  }
11840  else
11841  {
11842  maxactsub -= lb * vals[0];
11843  minactsub -= ub * vals[0];
11844  }
11845  assert(maxactsub > minactsub);
11846  ++v;
11847  }
11848 
11849  siderest = -SCIP_INVALID;
11850  allcoefintegral = TRUE;
11851 
11852  /* check if some variables always fit into the given constraint */
11853  for( ; v < nvars - 1; ++v )
11854  {
11855  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11856  break;
11857 
11858  if( !SCIPisIntegral(scip, vals[v]) )
11859  {
11860  allcoefintegral = FALSE;
11861  break;
11862  }
11863 
11864  /* calculate greatest common divisor for all general and binary variables */
11865  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11866 
11867  if( gcd == 1 )
11868  break;
11869 
11870  lb = SCIPvarGetLbGlobal(vars[v]);
11871  ub = SCIPvarGetUbGlobal(vars[v]);
11872 
11873  assert(!SCIPisInfinity(scip, -lb));
11874  assert(!SCIPisInfinity(scip, ub));
11875 
11876  /* update residual activities */
11877  if( vals[v] > 0 )
11878  {
11879  maxactsub -= ub * vals[v];
11880  minactsub -= lb * vals[v];
11881  }
11882  else
11883  {
11884  maxactsub -= lb * vals[v];
11885  minactsub -= ub * vals[v];
11886  }
11887  assert(SCIPisGE(scip, maxactsub, minactsub));
11888 
11889  if( hasrhs )
11890  {
11891  /* determine the remainder of the right hand side and the gcd */
11892  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11893  }
11894  else
11895  {
11896  /* determine the remainder of the left hand side and the gcd */
11897  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11898  if( SCIPisZero(scip, siderest) )
11899  siderest = gcd;
11900  }
11901 
11902  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11903  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11904 
11905  /* early termination if the activities deceed the gcd */
11906  if( offsetv == -1 && (rredundant || lredundant) )
11907  {
11908  redundant = TRUE;
11909  break;
11910  }
11911  }
11912  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11913 
11914  if( !redundant )
11915  {
11916  if( hasrhs )
11917  {
11918  /* determine the remainder of the right hand side and the gcd */
11919  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11920  }
11921  else
11922  {
11923  /* determine the remainder of the left hand side and the gcd */
11924  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11925  if( SCIPisZero(scip, siderest) )
11926  siderest = gcd;
11927  }
11928  }
11929  else
11930  ++v;
11931 
11932  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",
11933  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11934 
11935  /* to avoid inconsistencies due to numerics, check that the full and partial activities have
11936  * reasonable absolute values */
11937  numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL &&
11938  REALABS(minactsub) < MAXACTVAL;
11939 
11940  rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd);
11941  lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd;
11942 
11943  /* check if we can remove redundant variables */
11944  if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) )
11945  {
11946  SCIP_Real oldcoef;
11947 
11948  /* double check the redundancy */
11949 #ifndef NDEBUG
11950  SCIP_Real tmpminactsub = 0.0;
11951  SCIP_Real tmpmaxactsub = 0.0;
11952 
11953  /* recompute residual activities */
11954  for( w = v; w < nvars; ++w )
11955  {
11956  lb = SCIPvarGetLbGlobal(vars[w]);
11957  ub = SCIPvarGetUbGlobal(vars[w]);
11958 
11959  assert(!SCIPisInfinity(scip, -lb));
11960  assert(!SCIPisInfinity(scip, ub));
11961 
11962  /* update residual activities */
11963  if( vals[w] > 0 )
11964  {
11965  tmpmaxactsub += ub * vals[w];
11966  tmpminactsub += lb * vals[w];
11967  }
11968  else
11969  {
11970  tmpmaxactsub += lb * vals[w];
11971  tmpminactsub += ub * vals[w];
11972  }
11973  assert(tmpmaxactsub >= tmpminactsub);
11974  }
11975 
11976  if( hasrhs )
11977  {
11978  assert(offsetv == -1);
11979 
11980  /* determine the remainder of the right hand side and the gcd */
11981  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11982  }
11983  else
11984  {
11985  /* determine the remainder of the left hand side and the gcd */
11986  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11987  if( SCIPisZero(scip, siderest) )
11988  siderest = gcd;
11989  }
11990 
11991  /* is the redundancy really fulfilled */
11992  assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11993  (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11994 #endif
11995 
11996  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11997  nvars - v, SCIPconsGetName(cons));
11998 
11999  /* remove redundant variables */
12000  for( w = nvars - 1; w >= v; --w )
12001  {
12002  SCIP_CALL( delCoefPos(scip, cons, w) );
12003  }
12004  (*nchgcoefs) += (nvars - v);
12005 
12006  assert(w >= 0);
12007 
12008  oldcoef = vals[w];
12009 
12010  /* normalize constraint */
12011  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12012  assert(vars == consdata->vars);
12013  assert(vals == consdata->vals);
12014  assert(w < consdata->nvars);
12015 
12016  if( *infeasible )
12017  return SCIP_OKAY;
12018 
12019  /* compute new greatest common divisor due to normalization */
12020  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
12021  assert(gcd >= 1);
12022 
12023  /* update side */
12024  if( hasrhs )
12025  {
12026  /* replace old with new right hand side */
12027  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
12028  rhs = consdata->rhs;
12029  }
12030  else
12031  {
12032  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
12033  {
12034  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
12035  lhs = consdata->lhs;
12036  }
12037  else
12038  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
12039  }
12040  ++(*nchgsides);
12041 
12042  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12043  assert(!haslhs || !SCIPisNegative(scip, lhs));
12044 
12045  /* get new constraint data */
12046  nvars = consdata->nvars;
12047  assert(nvars > 0);
12048 
12049  allcoefintegral = TRUE;
12050 
12051 #ifndef NDEBUG
12052  /* check integrality */
12053  for( w = offsetv + 1; w < nvars; ++w )
12054  {
12055  assert(SCIPisIntegral(scip, vals[w]));
12056  }
12057 #endif
12058  SCIPdebugPrintCons(scip, cons, NULL);
12059  }
12060 
12061  /* try to find a better gcd, when having large coefficients */
12062  if( offsetv >= 0 && gcd == 1 )
12063  {
12064  /* calculate greatest common divisor for all general variables */
12065  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
12066 
12067  if( gcd > 1 )
12068  {
12069  gcd = -1;
12070  candpos = -1;
12071 
12072  for( v = nvars - 1; v > offsetv; --v )
12073  {
12074  assert(!SCIPisZero(scip, vals[v]));
12075  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
12076  break;
12077 
12078  if( !SCIPisIntegral(scip, vals[v]) )
12079  {
12080  allcoefintegral = FALSE;
12081  break;
12082  }
12083 
12084  oldgcd = gcd;
12085 
12086  if( gcd == -1 )
12087  {
12088  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12089  assert(gcd >= 1);
12090  }
12091  else
12092  {
12093  /* calculate greatest common divisor for all general and binary variables */
12094  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12095  }
12096 
12097  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12098  * can stop searching
12099  */
12100  if( gcd == 1 )
12101  {
12102  if( !SCIPvarIsBinary(vars[v]) )
12103  break;
12104 
12105  /* found candidate */
12106  if( candpos == -1 )
12107  {
12108  gcd = oldgcd;
12109  candpos = v;
12110  }
12111  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12112  else
12113  break;
12114  }
12115  }
12116  assert(v > offsetv || candpos > offsetv);
12117  }
12118  else
12119  candpos = -1;
12120  }
12121  else
12122  candpos = nvars - 1;
12123 
12124  /* check last coefficient for integrality */
12125  if( gcd > 1 && allcoefintegral && !redundant )
12126  {
12127  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12128  allcoefintegral = FALSE;
12129  }
12130 
12131  /* check for further necessary coefficient adjustments */
12132  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12133  {
12134  assert(offsetv + 1 < nvars);
12135  assert(0 <= candpos && candpos < nvars);
12136 
12137  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12138  {
12139  SCIP_Bool notchangable = FALSE;
12140 
12141 #ifndef NDEBUG
12142  /* check integrality */
12143  for( w = offsetv + 1; w < nvars; ++w )
12144  {
12145  assert(SCIPisIntegral(scip, vals[w]));
12146  }
12147 #endif
12148 
12149  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12150  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12151  {
12152  /* determine the remainder of the side and the gcd */
12153  if( hasrhs )
12154  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12155  else
12156  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12157  assert(rest >= 0);
12158  assert(rest < gcd);
12159 
12160  /* determine the remainder of the coefficient candidate and the gcd */
12161  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12162  assert(restcoef >= 1);
12163  assert(restcoef < gcd);
12164 
12165  if( hasrhs )
12166  {
12167  /* calculate new coefficient */
12168  if( restcoef > rest )
12169  newcoef = vals[candpos] - restcoef + gcd;
12170  else
12171  newcoef = vals[candpos] - restcoef;
12172  }
12173  else
12174  {
12175  /* calculate new coefficient */
12176  if( rest == 0 || restcoef < rest )
12177  newcoef = vals[candpos] - restcoef;
12178  else
12179  newcoef = vals[candpos] - restcoef + gcd;
12180  }
12181 
12182  /* done */
12183 
12184  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12185  * another with the big coefficient was set to 1
12186  */
12187  if( hasrhs && SCIPisZero(scip, newcoef) )
12188  {
12189  notchangable = TRUE;
12190  }
12191  else if( SCIPisZero(scip, newcoef) )
12192  {
12193  /* delete old redundant coefficient */
12194  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12195  ++(*nchgcoefs);
12196  }
12197  else
12198  {
12199  /* replace old with new coefficient */
12200  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12201  ++(*nchgcoefs);
12202  }
12203  }
12204  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12205  {
12206  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12207  }
12208 
12209  /* correct side and big coefficients */
12210  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12211  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12212  {
12213  if( haslhs )
12214  {
12215  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12216 
12217  SCIP_CALL( chgLhs(scip, cons, newcoef) );
12218  ++(*nchgsides);
12219  }
12220  else
12221  {
12222  assert(hasrhs);
12223  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12224 
12225  SCIP_CALL( chgRhs(scip, cons, newcoef) );
12226  ++(*nchgsides);
12227  }
12228 
12229  /* correct coefficients up front */
12230  for( w = offsetv; w >= 0; --w )
12231  {
12232  assert(vals[w] > 0);
12233 
12234  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12235  }
12236  (*nchgcoefs) += (offsetv + 1);
12237  }
12238 
12239  if( !notchangable )
12240  {
12241  /* normalize constraint */
12242  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12243  assert(vars == consdata->vars);
12244  assert(vals == consdata->vals);
12245 
12246  if( *infeasible )
12247  return SCIP_OKAY;
12248 
12249  /* get new constraint data */
12250  nvars = consdata->nvars;
12251  assert(nvars >= 2);
12252 
12253  SCIPdebugPrintCons(scip, cons, NULL);
12254 
12255  lhs = consdata->lhs;
12256  rhs = consdata->rhs;
12257  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12258  assert(!haslhs || !SCIPisNegative(scip, lhs));
12259  }
12260  }
12261  }
12262  }
12263 
12264  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12265  /* no continuous variables are left over */
12266  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12267  return SCIP_OKAY;
12268 
12269  onlybin = TRUE;
12270  allcoefintegral = TRUE;
12271  /* check if all variables are of binary type */
12272  for( v = nvars - 1; v >= 0; --v )
12273  {
12274  if( !SCIPvarIsBinary(vars[v]) )
12275  onlybin = FALSE;
12276  if( !SCIPisIntegral(scip, vals[v]) )
12277  allcoefintegral = FALSE;
12278  }
12279 
12280  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12281  * hand side or bigger than the left hand side respectively, so we can make all of them integral
12282  *
12283  * @todo there are some steps missing ....
12284  */
12285  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12286  {
12287  SCIP_Real val;
12288  SCIP_Real newval;
12289  SCIP_Real frac = 0.0;
12290  SCIP_Bool found = FALSE;
12291 
12292  if( hasrhs )
12293  {
12294  if( allcoefintegral )
12295  {
12296  /* replace old with new right hand side */
12297  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12298  ++(*nchgsides);
12299  }
12300  else
12301  {
12302  siderest = rhs - SCIPfloor(scip, rhs);
12303 
12304  /* try to round down all non-integral coefficients */
12305  for( v = nvars - 1; v >= 0; --v )
12306  {
12307  val = vals[v];
12308 
12309  /* add up all possible fractional parts */
12310  if( !SCIPisIntegral(scip, val) )
12311  {
12312  lb = SCIPvarGetLbGlobal(vars[v]);
12313  ub = SCIPvarGetUbGlobal(vars[v]);
12314 
12315  /* at least one bound need to be at zero */
12316  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12317  return SCIP_OKAY;
12318 
12319  /* swap bounds for 'standard' form */
12320  if( !SCIPisFeasZero(scip, lb) )
12321  {
12322  ub = lb;
12323  val *= -1;
12324  }
12325 
12326  found = TRUE;
12327 
12328  frac += (val - SCIPfloor(scip, val)) * ub;
12329 
12330  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12331  *
12332  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12333  * x3, x4 set to 1 would be infeasible but feasible after flooring
12334  */
12335  if( SCIPisGT(scip, frac, siderest) )
12336  return SCIP_OKAY;
12337  }
12338  }
12339  assert(v == -1);
12340 
12341  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12342 
12343  /* round rhs and coefficients to integral values */
12344  if( found )
12345  {
12346  for( v = nvars - 1; v >= 0; --v )
12347  {
12348  val = vals[v];
12349 
12350  /* add the whole fractional part */
12351  if( !SCIPisIntegral(scip, val) )
12352  {
12353  lb = SCIPvarGetLbGlobal(vars[v]);
12354 
12355  if( SCIPisFeasZero(scip, lb) )
12356  newval = SCIPfloor(scip, val);
12357  else
12358  newval = SCIPceil(scip, val);
12359 
12360  if( SCIPisZero(scip, newval) )
12361  {
12362  /* delete old redundant coefficient */
12363  SCIP_CALL( delCoefPos(scip, cons, v) );
12364  ++(*nchgcoefs);
12365  }
12366  else
12367  {
12368  /* replace old with new coefficient */
12369  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12370  ++(*nchgcoefs);
12371  }
12372  }
12373  }
12374  }
12375 
12376  /* replace old with new right hand side */
12377  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12378  ++(*nchgsides);
12379  }
12380  }
12381  else
12382  {
12383  if( allcoefintegral )
12384  {
12385  /* replace old with new left hand side */
12386  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12387  ++(*nchgsides);
12388  }
12389  else
12390  {
12391  /* cannot floor left hand side to zero */
12392  if( SCIPisLT(scip, lhs, 1.0) )
12393  return SCIP_OKAY;
12394 
12395  siderest = lhs - SCIPfloor(scip, lhs);
12396 
12397  /* try to round down all non-integral coefficients */
12398  for( v = nvars - 1; v >= 0; --v )
12399  {
12400  val = vals[v];
12401 
12402  /* add up all possible fractional parts */
12403  if( !SCIPisIntegral(scip, val) )
12404  {
12405  lb = SCIPvarGetLbGlobal(vars[v]);
12406  ub = SCIPvarGetUbGlobal(vars[v]);
12407 
12408  /* at least one bound need to be at zero */
12409  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12410  return SCIP_OKAY;
12411 
12412  /* swap bounds for 'standard' form */
12413  if( !SCIPisFeasZero(scip, lb) )
12414  {
12415  ub = lb;
12416  val *= -1;
12417  }
12418 
12419  /* cannot floor to zero */
12420  if( SCIPisLT(scip, val, 1.0) )
12421  return SCIP_OKAY;
12422 
12423  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12424  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12425  return SCIP_OKAY;
12426 
12427  found = TRUE;
12428 
12429  frac += (val - SCIPfloor(scip, val)) * ub;
12430 
12431  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12432  * fractional parts of the variables, we cannot tighten the coefficients
12433  *
12434  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12435  * x2-x4 set to 1 would be feasible but not after flooring
12436  */
12437  if( SCIPisGE(scip, frac, 1 + siderest) )
12438  return SCIP_OKAY;
12439  }
12440  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12441  else
12442  return SCIP_OKAY;
12443  }
12444  assert(v == -1);
12445 
12446  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12447 
12448  /* round lhs and coefficients to integral values */
12449  if( found )
12450  {
12451  for( v = nvars - 1; v >= 0; --v )
12452  {
12453  val = vals[v];
12454 
12455  /* add the whole fractional part */
12456  if( !SCIPisIntegral(scip, val) )
12457  {
12458  lb = SCIPvarGetLbGlobal(vars[v]);
12459 
12460  if( SCIPisFeasZero(scip, lb) )
12461  newval = SCIPfloor(scip, val);
12462  else
12463  newval = SCIPceil(scip, val);
12464 
12465  if( SCIPisZero(scip, newval) )
12466  {
12467  /* delete old redundant coefficient */
12468  SCIP_CALL( delCoefPos(scip, cons, v) );
12469  ++(*nchgcoefs);
12470  }
12471  else
12472  {
12473  /* replace old with new coefficient */
12474  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12475  ++(*nchgcoefs);
12476  }
12477  }
12478  }
12479  }
12480 
12481  /* replace old with new left hand side */
12482  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12483  ++(*nchgsides);
12484  }
12485  }
12486 
12487  /* normalize constraint */
12488  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12489  assert(vars == consdata->vars);
12490  assert(vals == consdata->vals);
12491 
12492  if( *infeasible )
12493  return SCIP_OKAY;
12494 
12495  rhs = consdata->rhs;
12496  lhs = consdata->lhs;
12497 
12498  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12499  assert(!haslhs || !SCIPisNegative(scip, lhs));
12500 
12501  SCIPdebugPrintCons(scip, cons, NULL);
12502 
12503  nvars = consdata->nvars;
12504  if( nvars < 2 )
12505  return SCIP_OKAY;
12506 
12507  allcoefintegral = TRUE;
12508 #ifndef NDEBUG
12509  /* debug check if all coefficients are really integral */
12510  for( v = nvars - 1; v >= 0; --v )
12511  assert(SCIPisIntegral(scip, vals[v]));
12512 #endif
12513  }
12514 
12515  /* @todo following can also work on non integral coefficients, need more investigation */
12516  /* only check constraints with integral coefficients on all integral variables */
12517  if( !allcoefintegral )
12518  return SCIP_OKAY;
12519 
12520  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12521  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12522  return SCIP_OKAY;
12523 
12524  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12525  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12526  return SCIP_OKAY;
12527 
12528  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12529  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12530  return SCIP_OKAY;
12531 
12532  assert(nvars >= 2);
12533 
12534  /* start gcd procedure for all variables */
12535  do
12536  {
12537  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12538  SCIPdebug( oldnchgsides = *nchgsides; )
12539 
12540  /* stop if we have two coeffcients which are one in absolute value */
12541  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12542  return SCIP_OKAY;
12543 
12544  gcd = -1;
12545 
12546  /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12547  * because coefficients of non-binary variables might have changed to zero */
12548  if( !onlybin )
12549  {
12550  foundbin = -1;
12551  onlybin = TRUE;
12552 
12553  for( v = nvars - 1; v >= 0; --v )
12554  {
12555  assert(!SCIPisZero(scip, vals[v]));
12556  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12557 
12558  if( SCIPvarIsBinary(vars[v]) )
12559  {
12560  if( foundbin == -1 )
12561  foundbin = v;
12562  continue;
12563  }
12564  else
12565  onlybin = FALSE;
12566 
12567  absval = REALABS(vals[v]);
12568  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12569  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12570  */
12571  assert(SCIPisFeasIntegral(scip, absval));
12572 
12573  if( gcd == -1 )
12574  {
12575  gcd = (SCIP_Longint)(absval + feastol);
12576  assert(gcd >= 1);
12577  }
12578  else
12579  {
12580  /* calculate greatest common divisor for all general variables */
12581  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12582  }
12583  if( gcd == 1 )
12584  break;
12585  }
12586  }
12587  else
12588  foundbin = nvars - 1;
12589 
12590  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12591  if( gcd == 1 || foundbin == -1)
12592  return SCIP_OKAY;
12593 
12594  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12595 
12596  candpos = -1;
12597  candpos2 = -1;
12598 
12599  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12600  * change the coefficient
12601  */
12602  for( v = foundbin; v >= 0; --v )
12603  {
12604  if( onlybin || SCIPvarIsBinary(vars[v]) )
12605  {
12606  absval = REALABS(vals[v]);
12607  /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12608  * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12609  */
12610  assert(SCIPisFeasIntegral(scip, absval));
12611 
12612  oldgcd = gcd;
12613 
12614  if( gcd == -1 )
12615  {
12616  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12617  assert(gcd >= 1);
12618  }
12619  else
12620  {
12621  /* calculate greatest common divisor for all general and binary variables */
12622  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12623  }
12624 
12625  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12626  * can terminate
12627  */
12628  if( gcd == 1 )
12629  {
12630  /* found candidate */
12631  if( candpos == -1 )
12632  {
12633  gcd = oldgcd;
12634  candpos = v;
12635 
12636  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12637  * the coefficient change
12638  */
12639  if( onlybin && v == foundbin - 1 )
12640  candpos2 = foundbin;
12641  }
12642  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12643  else
12644  {
12645  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12646  {
12647  assert(candpos2 == nvars - 1);
12648 
12649  /* take new candidates */
12650  candpos = candpos2;
12651 
12652  /* recalculate gcd from scratch */
12653  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12654  assert(gcd >= 1);
12655 
12656  /* calculate greatest common divisor for all general and binary variables */
12657  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12658  if( gcd == 1 )
12659  return SCIP_OKAY;
12660  }
12661  else
12662  /* cannot determine a possible coefficient for reduction */
12663  return SCIP_OKAY;
12664  }
12665  }
12666  }
12667  }
12668  assert(gcd >= 2);
12669 
12670  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12671  * further
12672  */
12673  assert(candpos >= 0 && candpos < nvars);
12674 
12675  /* all variables and all coefficients are integral, so the side should be too */
12676  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12677 
12678  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12679  * @see normalizeCons()
12680  */
12681  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12682  assert(!haslhs || !SCIPisNegative(scip, lhs));
12683 
12684  /* determine the remainder of the side and the gcd */
12685  if( hasrhs )
12686  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12687  else
12688  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12689  assert(rest >= 0);
12690  assert(rest < gcd);
12691 
12692  /* determine the remainder of the coefficient candidate and the gcd */
12693  if( vals[candpos] < 0 )
12694  {
12695  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12696  assert(restcoef <= -1);
12697  restcoef += gcd;
12698  }
12699  else
12700  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12701  assert(restcoef >= 1);
12702  assert(restcoef < gcd);
12703 
12704  if( hasrhs )
12705  {
12706  if( rest > 0 )
12707  {
12708  /* replace old with new right hand side */
12709  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12710  ++(*nchgsides);
12711  }
12712 
12713  /* calculate new coefficient */
12714  if( restcoef > rest )
12715  newcoef = vals[candpos] - restcoef + gcd;
12716  else
12717  newcoef = vals[candpos] - restcoef;
12718  }
12719  else
12720  {
12721  if( rest > 0 )
12722  {
12723  /* replace old with new left hand side */
12724  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12725  ++(*nchgsides);
12726  }
12727 
12728  /* calculate new coefficient */
12729  if( rest == 0 || restcoef < rest )
12730  newcoef = vals[candpos] - restcoef;
12731  else
12732  newcoef = vals[candpos] - restcoef + gcd;
12733  }
12734  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12735 
12736  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));
12737 
12738  if( SCIPisZero(scip, newcoef) )
12739  {
12740  /* delete redundant coefficient */
12741  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12742  }
12743  else
12744  {
12745  /* replace old with new coefficient */
12746  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12747  }
12748  ++(*nchgcoefs);
12749 
12750  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12751  SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12752  assert(vars == consdata->vars);
12753  assert(vals == consdata->vals);
12754 
12755  if( *infeasible )
12756  return SCIP_OKAY;
12757 
12758  SCIPdebugPrintCons(scip, cons, NULL);
12759 
12760  rhs = consdata->rhs;
12761  lhs = consdata->lhs;
12762  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12763  assert(!haslhs || !SCIPisNegative(scip, lhs));
12764 
12765  nvars = consdata->nvars;
12766 
12767  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));
12768  }
12769  while( nvars >= 2 );
12770 
12771  return SCIP_OKAY;
12772 }
12773 
12774 
12775 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12776  * cons0 := a * cons0 + b * cons1,
12777  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12778  * for numerical stability, we will only accept integral a and b;
12779  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12780  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12781  */
12782 static
12784  SCIP* scip, /**< SCIP data structure */
12785  SCIP_CONS* cons0, /**< (in)equality to modify */
12786  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12787  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12788  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12789  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12790  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12791  int nvarscommon, /**< number of variables, that appear in both constraints */
12792  int commonidxweight, /**< variable weight sum of common variables */
12793  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12794  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12795  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12796  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12797  SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */
12798  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
12799  )
12800 {
12801  SCIP_CONSDATA* consdata0;
12802  SCIP_CONSDATA* consdata1;
12803  SCIP_Real a;
12804  SCIP_Real b;
12805  SCIP_Real aggrcoef;
12806  SCIP_Real scalarsum;
12807  SCIP_Real bestscalarsum;
12808  SCIP_Bool betterscalarsum;
12809  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12810  int varweight;
12811  int nvars;
12812  int bestvarweight;
12813  int bestnvars;
12814  int bestv;
12815  int v;
12816  int i;
12817 
12818  assert(scip != NULL);
12819  assert(cons0 != NULL);
12820  assert(cons1 != NULL);
12821  assert(commonidx0 != NULL);
12822  assert(commonidx1 != NULL);
12823  assert(diffidx0minus1 != NULL);
12824  assert(diffidx1minus0 != NULL);
12825  assert(nvarscommon >= 1);
12826  assert(commonidxweight >= nvarscommon);
12827  assert(nchgcoefs != NULL);
12828  assert(aggregated != NULL);
12829 
12830  assert(SCIPconsIsActive(cons0));
12831  assert(SCIPconsIsActive(cons1));
12832 
12833  *infeasible = FALSE;
12834 
12835  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12836 
12837  /* cons0 is an (in)equality */
12838  consdata0 = SCIPconsGetData(cons0);
12839  assert(consdata0 != NULL);
12840  assert(consdata0->nvars >= 1);
12841  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12842  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12843 
12844  /* cons1 is an equality */
12845  consdata1 = SCIPconsGetData(cons1);
12846  assert(consdata1 != NULL);
12847  assert(consdata1->nvars >= 1);
12848  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12849  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12850 
12851  *aggregated = FALSE;
12852 
12853  /* search for the best common variable such that
12854  * val1[var] * consdata0 - val0[var] * consdata1
12855  * has least weighted number of variables
12856  */
12857  bestvarweight = commonidxweight + diffidx0minus1weight;
12858  bestnvars = consdata0->nvars;
12859  bestv = -1;
12860  bestscalarsum = 0.0;
12861  commonvarlindependent = TRUE;
12862  for( v = 0; v < nvarscommon; ++v )
12863  {
12864  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12865  a = consdata1->vals[commonidx1[v]];
12866  b = -consdata0->vals[commonidx0[v]];
12867 
12868  /* only try aggregation, if coefficients are integral (numerical stability) */
12869  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12870  {
12871  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12872  varweight = diffidx0minus1weight + diffidx1minus0weight;
12873  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12874  scalarsum = REALABS(a) + REALABS(b);
12875  betterscalarsum = (scalarsum < bestscalarsum);
12876  for( i = 0; i < nvarscommon
12877  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12878  {
12879  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12880  if( !SCIPisZero(scip, aggrcoef) )
12881  {
12882  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12883  nvars++;
12884  }
12885  }
12886  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12887  {
12888  bestv = v;
12889  bestvarweight = varweight;
12890  bestnvars = nvars;
12891  bestscalarsum = scalarsum;
12892  }
12893  }
12894 
12895  /* update commonvarlindependent flag, if still TRUE:
12896  * 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
12897  */
12898  if( commonvarlindependent && v > 0 )
12899  commonvarlindependent = SCIPisEQ(scip,
12900  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12901  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12902  }
12903 
12904  /* if better aggregation was found, create new constraint and delete old one */
12905  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12906  {
12907  SCIP_CONS* newcons;
12908  SCIP_CONSDATA* newconsdata;
12909  SCIP_VAR** newvars;
12910  SCIP_Real* newvals;
12911  SCIP_Real newlhs;
12912  SCIP_Real newrhs;
12913  int newnvars;
12914 
12915  if( bestv != -1 )
12916  {
12917  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12918  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12919  {
12920  a = consdata1->vals[commonidx1[bestv]];
12921  b = -consdata0->vals[commonidx0[bestv]];
12922  }
12923  else
12924  {
12925  a = -consdata1->vals[commonidx1[bestv]];
12926  b = consdata0->vals[commonidx0[bestv]];
12927  }
12928  assert(SCIPisIntegral(scip, a));
12929  assert(SCIPisPositive(scip, a));
12930  assert(SCIPisIntegral(scip, b));
12931  assert(!SCIPisZero(scip, b));
12932  }
12933  else
12934  {
12935  assert(commonvarlindependent);
12936  if( consdata1->vals[commonidx1[0]] > 0.0 )
12937  {
12938  a = consdata1->vals[commonidx1[0]];
12939  b = -consdata0->vals[commonidx0[0]];
12940  }
12941  else
12942  {
12943  a = -consdata1->vals[commonidx1[0]];
12944  b = consdata0->vals[commonidx0[0]];
12945  }
12946  assert(SCIPisPositive(scip, a));
12947  assert(!SCIPisZero(scip, b));
12948 
12949  /* if a/b is integral, then we can easily choose integer multipliers */
12950  if( SCIPisIntegral(scip, a/b) )
12951  {
12952  if( a/b > 0 )
12953  {
12954  a /= b;
12955  b = 1.0;
12956  }
12957  else
12958  {
12959  a /= -b;
12960  b = -1.0;
12961  }
12962  }
12963 
12964  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12965  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12966  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12967  }
12968 
12969  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12970  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12971  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12972  SCIPdebugPrintCons(scip, cons0, NULL);
12973  SCIPdebugPrintCons(scip, cons1, NULL);
12974 
12975  /* get temporary memory for creating the new linear constraint */
12976  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12977  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12978 
12979  /* calculate the common coefficients, if we have not recognized linear dependency */
12980  newnvars = 0;
12981  if( !commonvarlindependent )
12982  {
12983  for( i = 0; i < nvarscommon; ++i )
12984  {
12985  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12986  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12987 
12988  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12989  if( !SCIPisZero(scip, aggrcoef) )
12990  {
12991  assert(newnvars < bestnvars);
12992  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12993  newvals[newnvars] = aggrcoef;
12994  newnvars++;
12995  }
12996  }
12997  }
12998  else
12999  {
13000  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
13001 #ifndef NDEBUG
13002  for( i = 0; i < nvarscommon; ++i )
13003  {
13004  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
13005  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
13006 
13007  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
13008  assert(SCIPisZero(scip, aggrcoef));
13009  }
13010 #endif
13011  }
13012 
13013  /* calculate the coefficients appearing in cons0 but not in cons1 */
13014  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
13015  {
13016  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
13017 
13018  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
13019  assert(!SCIPisZero(scip, aggrcoef));
13020  assert(newnvars < bestnvars);
13021  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
13022  newvals[newnvars] = aggrcoef;
13023  newnvars++;
13024  }
13025 
13026  /* calculate the coefficients appearing in cons1 but not in cons0 */
13027  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
13028  {
13029  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
13030 
13031  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
13032  assert(!SCIPisZero(scip, aggrcoef));
13033  assert(newnvars < bestnvars);
13034  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
13035  newvals[newnvars] = aggrcoef;
13036  newnvars++;
13037  }
13038  assert(newnvars == bestnvars);
13039 
13040  /* calculate the new left and right hand side of the (in)equality */
13041  assert(!SCIPisInfinity(scip, -consdata1->lhs));
13042  assert(!SCIPisInfinity(scip, consdata1->rhs));
13043  if( SCIPisInfinity(scip, -consdata0->lhs) )
13044  newlhs = -SCIPinfinity(scip);
13045  else
13046  newlhs = a * consdata0->lhs + b * consdata1->lhs;
13047  if( SCIPisInfinity(scip, consdata0->rhs) )
13048  newrhs = SCIPinfinity(scip);
13049  else
13050  newrhs = a * consdata0->rhs + b * consdata1->rhs;
13051 
13052  /* create the new linear constraint */
13053  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
13055  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
13056  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
13058 
13059  newconsdata = SCIPconsGetData(newcons);
13060  assert(newconsdata != NULL);
13061 
13062  /* copy the upgraded flag from the old cons0 to the new constraint */
13063  newconsdata->upgraded = consdata0->upgraded;
13064 
13065  /* normalize the new constraint */
13066  SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
13067 
13068  if( *infeasible )
13069  goto TERMINATE;
13070 
13071  /* check, if we really want to use the new constraint instead of the old one:
13072  * use the new one, if the maximum norm doesn't grow too much
13073  */
13074  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
13075  {
13076  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
13077  SCIPdebugPrintCons(scip, newcons, NULL);
13078 
13079  /* update the statistics: we changed all coefficients */
13080  if( !consdata0->upgraded )
13081  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
13082  *aggregated = TRUE;
13083 
13084  /* delete the old constraint, and add the new linear constraint to the problem */
13085  SCIP_CALL( SCIPdelCons(scip, cons0) );
13086  SCIP_CALL( SCIPaddCons(scip, newcons) );
13087  }
13088 
13089  TERMINATE:
13090  /* release the new constraint */
13091  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
13092 
13093  /* free temporary memory */
13094  SCIPfreeBufferArray(scip, &newvals);
13095  SCIPfreeBufferArray(scip, &newvars);
13096  }
13097 
13098  return SCIP_OKAY;
13099 }
13100 
13101 /** gets the key of the given element */
13102 static
13103 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
13104 { /*lint --e{715}*/
13105  /* the key is the element itself */
13106  return elem;
13107 }
13108 
13109 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13110  * coefficients are either equal or negated
13111  */
13112 static
13113 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13114 {
13115  SCIP* scip;
13116  SCIP_CONSDATA* consdata1;
13117  SCIP_CONSDATA* consdata2;
13118  SCIP_Real cons1scale;
13119  SCIP_Real cons2scale;
13120  int i;
13121 
13122  assert(key1 != NULL);
13123  assert(key2 != NULL);
13124  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13125  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13126  assert(consdata1->indexsorted);
13127  assert(consdata2->indexsorted);
13128 
13129  scip = (SCIP*)userptr;
13130  assert(scip != NULL);
13131 
13132  /* if it is the same constraint we dont need to check anything */
13133  if( key1 == key2 )
13134  return TRUE;
13135 
13136  /* checks trivial case */
13137  if( consdata1->nvars != consdata2->nvars )
13138  return FALSE;
13139 
13140  /* tests if variables are equal */
13141  for( i = 0; i < consdata1->nvars; ++i )
13142  {
13143  if( consdata1->vars[i] != consdata2->vars[i] )
13144  {
13145  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13146  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13147  return FALSE;
13148  }
13149  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13150  }
13151 
13152  /* compute scale before comparing coefficients of constraints */
13153  cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13154  cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13155 
13156  /* tests if coefficients are equal with the computed scale */
13157  for( i = 0; i < consdata1->nvars; ++i )
13158  {
13159  SCIP_Real val1;
13160  SCIP_Real val2;
13161 
13162  val1 = consdata1->vals[i] * cons1scale;
13163  val2 = consdata2->vals[i] * cons2scale;
13164 
13165  if( !SCIPisEQ(scip, val1, val2) )
13166  return FALSE;
13167  }
13168 
13169  return TRUE;
13170 }
13171 
13172 /** returns the hash value of the key */
13173 static
13174 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13175 {
13176  SCIP_CONSDATA* consdata;
13177  int minidx;
13178  int mididx;
13179  int maxidx;
13180  SCIP_Real scale;
13181 #ifndef NDEBUG
13182  SCIP* scip;
13183 
13184  scip = (SCIP*)userptr;
13185  assert(scip != NULL);
13186 #endif
13187 
13188  assert(key != NULL);
13189  consdata = SCIPconsGetData((SCIP_CONS*)key);
13190  assert(consdata != NULL);
13191  assert(consdata->nvars > 0);
13192 
13193  assert(consdata->indexsorted);
13194 
13195  minidx = SCIPvarGetIndex(consdata->vars[0]);
13196  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13197  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13198  scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13199 
13200  /* using only the variable indices as hash, since the values are compared by epsilon */
13201  return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13202  mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13203  maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13204 }
13205 
13206 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13207  * prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13208  */
13209 static
13210 unsigned int getParallelConsKey(
13211  SCIP_CONS* cons /**< linear constraint */
13212  )
13213 {
13214  SCIP_CONSDATA* consdata;
13215 
13216  assert(cons != NULL);
13217 
13218  consdata = SCIPconsGetData(cons);
13219  assert(consdata != NULL);
13220 
13221  return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13222 }
13223 
13224 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13225  * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13226  * and all others are removed from the hashtable and stored in the given array
13227  */
13228 static
13230  SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */
13231  SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table;
13232  * upon return will contain the constraint that should be kept */
13233  SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given;
13234  * these constraints where removed from the hashtable */
13235  int* nparallelconss /**< pointer to return number of parallel constraints */
13236  )
13237 {
13238  SCIP_CONS* parallelcons;
13239  unsigned int querykey;
13240 
13241  *nparallelconss = 0;
13242  querykey = getParallelConsKey(*querycons);
13243 
13244  while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13245  {
13246  unsigned int conskey = getParallelConsKey(parallelcons);
13247 
13248  if( conskey < querykey )
13249  {
13250  parallelconss[(*nparallelconss)++] = *querycons;
13251  *querycons = parallelcons;
13252  querykey = conskey;
13253  }
13254  else
13255  {
13256  parallelconss[(*nparallelconss)++] = parallelcons;
13257  }
13258 
13259  /* if the constraint that just came out of the hash table is the one that is kept,
13260  * we do not need to look into the hashtable again, since the invariant is that
13261  * in the hashtable only pair-wise non-parallel constraints are contained.
13262  * For the original querycons, however, multiple constraints that compare equal (=parallel)
13263  * could be contained due to non-transitivity of the equality comparison.
13264  * Also we can return immediately, since parallelcons is already contained in the
13265  * hashtable and we do not need to remove and reinsert it.
13266  */
13267  if( *querycons == parallelcons )
13268  return SCIP_OKAY;
13269 
13270  /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13271  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13272  }
13273 
13274  /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13275  * comnpares equal to querycons at this point
13276  */
13277 #ifndef NDEBUG
13278  SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13279 #else
13280  SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13281 #endif
13282 
13283  return SCIP_OKAY;
13284 }
13285 
13286 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13287  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13288  */
13289 static
13291  SCIP* scip, /**< SCIP data structure */
13292  BMS_BLKMEM* blkmem, /**< block memory */
13293  SCIP_CONS** conss, /**< constraint set */
13294  int nconss, /**< number of constraints in constraint set */
13295  int* firstchange, /**< pointer to store first changed constraint */
13296  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13297  int* ndelconss, /**< pointer to count number of deleted constraints */
13298  int* nchgsides /**< pointer to count number of changed left/right hand sides */
13299  )
13300 {
13301  SCIP_HASHTABLE* hashtable;
13302  SCIP_CONS** parallelconss;
13303  int nparallelconss;
13304  int hashtablesize;
13305  int c;
13306 
13307  assert(scip != NULL);
13308  assert(blkmem != NULL);
13309  assert(conss != NULL);
13310  assert(firstchange != NULL);
13311  assert(cutoff != NULL);
13312  assert(ndelconss != NULL);
13313  assert(nchgsides != NULL);
13314 
13315  /* create a hash table for the constraint set */
13316  hashtablesize = nconss;
13317  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13318  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13319 
13320  SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13321 
13322  /* check all constraints in the given set for redundancy */
13323  for( c = 0; c < nconss; ++c )
13324  {
13325  SCIP_CONS* cons0;
13326  SCIP_CONSDATA* consdata0;
13327 
13328  cons0 = conss[c];
13329 
13330  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13331  continue;
13332 
13333  /* do not check for parallel constraints if they should not be upgraded */
13334  if ( SCIPconsGetNUpgradeLocks(cons0) > 0 )
13335  continue;
13336 
13337  /* check for interuption */
13338  if( c % 1000 == 0 && SCIPisStopped(scip) )
13339  break;
13340 
13341  /* sorts the constraint */
13342  consdata0 = SCIPconsGetData(cons0);
13343  assert(consdata0 != NULL);
13344  SCIP_CALL( consdataSort(scip, consdata0) );
13345  assert(consdata0->indexsorted);
13346 
13347  /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13348  * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13349  * first variable is positive
13350  * Also inserts cons0 into the hashtable.
13351  */
13352  SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13353 
13354  if( nparallelconss != 0 )
13355  {
13356  SCIP_Real lhs;
13357  SCIP_Real rhs;
13358 
13359  int i;
13360 
13361  /* cons0 may have been changed in retrieveParallelConstraints() */
13362  consdata0 = SCIPconsGetData(cons0);
13363 
13364  lhs = consdata0->lhs;
13365  rhs = consdata0->rhs;
13366 
13367  for( i = 0; i < nparallelconss; ++i )
13368  {
13369  SCIP_CONS* consdel;
13370  SCIP_CONSDATA* consdatadel;
13371  SCIP_Real scale;
13372 
13373  consdel = parallelconss[i];
13374  consdatadel = SCIPconsGetData(consdel);
13375 
13376  /* do not delete constraint if it should not be upgraded */
13377  if ( SCIPconsGetNUpgradeLocks(consdel) > 0 )
13378  continue;
13379 
13380  assert(SCIPconsIsActive(consdel));
13381  assert(!SCIPconsIsModifiable(consdel));
13382 
13383  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13384  * delete old constraints afterwards
13385  */
13386  assert(consdatadel != NULL);
13387  assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13388 
13389  assert(consdatadel->indexsorted);
13390  assert(consdata0->vars[0] == consdatadel->vars[0]);
13391 
13392  scale = consdata0->vals[0] / consdatadel->vals[0];
13393  assert(scale != 0.0);
13394 
13395  /* in debug mode, check that all coefficients are equal with respect to epsilon
13396  * if the constraints are in equilibrium scale
13397  */
13398 #ifndef NDEBUG
13399  {
13400  int k;
13401  SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13402  SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13403 
13404  for( k = 0; k < consdata0->nvars; ++k )
13405  {
13406  assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13407  }
13408  }
13409 #endif
13410 
13411  if( scale > 0.0 )
13412  {
13413  /* the coefficients of both constraints are parallel with a positive scale */
13414  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13415  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13416  SCIPdebugPrintCons(scip, cons0, NULL);
13417  SCIPdebugPrintCons(scip, consdel, NULL);
13418 
13419  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13420  lhs = MAX(scale * consdatadel->lhs, lhs);
13421 
13422  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13423  rhs = MIN(scale * consdatadel->rhs, rhs);
13424  }
13425  else
13426  {
13427  /* the coefficients of both rows are negations */
13428  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13429  SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13430  SCIPdebugPrintCons(scip, cons0, NULL);
13431  SCIPdebugPrintCons(scip, consdel, NULL);
13432 
13433  if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13434  lhs = MAX(scale * consdatadel->rhs, lhs);
13435 
13436  if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13437  rhs = MIN(scale * consdatadel->lhs, rhs);
13438  }
13439 
13440  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13441  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13442 
13443  /* delete consdel */
13444  assert( ! consdata0->upgraded || consdatadel->upgraded );
13445  SCIP_CALL( SCIPdelCons(scip, consdel) );
13446  if( !consdatadel->upgraded )
13447  (*ndelconss)++;
13448  }
13449 
13450  if( SCIPisFeasLT(scip, rhs, lhs) )
13451  {
13452  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13453  *cutoff = TRUE;
13454  break;
13455  }
13456 
13457  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13458  if( lhs > rhs )
13459  {
13460  rhs = (lhs + rhs)/2;
13461  lhs = rhs;
13462  }
13463 
13464  /* update lhs and rhs of cons0 */
13465  SCIP_CALL( chgLhs(scip, cons0, lhs) );
13466  SCIP_CALL( chgRhs(scip, cons0, rhs) );
13467 
13468  /* update the first changed constraint to begin the next aggregation round with */
13469  if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13470  *firstchange = SCIPconsGetPos(cons0);
13471 
13472  assert(SCIPconsIsActive(cons0));
13473  }
13474  }
13475 #ifdef SCIP_MORE_DEBUG
13476  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13478 #endif
13479 
13480  SCIPfreeBufferArray(scip, &parallelconss);
13481 
13482  /* free hash table */
13483  SCIPhashtableFree(&hashtable);
13484 
13485  return SCIP_OKAY;
13486 }
13487 
13488 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13489  * and removes or changes constraint accordingly
13490  */
13491 static
13493  SCIP* scip, /**< SCIP data structure */
13494  SCIP_CONS** conss, /**< constraint set */
13495  int firstchange, /**< first constraint that changed since last pair preprocessing round */
13496  int chkind, /**< index of constraint to check against all prior indices upto startind */
13497  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13498  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13499  int* ndelconss, /**< pointer to count number of deleted constraints */
13500  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
13501  int* nchgcoefs /**< pointer to count number of changed coefficients */
13502  )
13503 {
13504  SCIP_CONS* cons0;
13505  SCIP_CONSDATA* consdata0;
13506  int* commonidx0;
13507  int* commonidx1;
13508  int* diffidx0minus1;
13509  int* diffidx1minus0;
13510  uint64_t possignature0;
13511  uint64_t negsignature0;
13512  SCIP_Bool cons0changed;
13513  SCIP_Bool cons0isequality;
13514  int diffidx1minus0size;
13515  int c;
13516  SCIP_Real cons0lhs;
13517  SCIP_Real cons0rhs;
13518  SCIP_Bool cons0upgraded;
13519 
13520  assert(scip != NULL);
13521  assert(conss != NULL);
13522  assert(firstchange <= chkind);
13523  assert(cutoff != NULL);
13524  assert(ndelconss != NULL);
13525  assert(nchgsides != NULL);
13526  assert(nchgcoefs != NULL);
13527 
13528  /* get the constraint to be checked against all prior constraints */
13529  cons0 = conss[chkind];
13530  assert(cons0 != NULL);
13531  assert(SCIPconsIsActive(cons0));
13532  assert(!SCIPconsIsModifiable(cons0));
13533 
13534  consdata0 = SCIPconsGetData(cons0);
13535  assert(consdata0 != NULL);
13536  assert(consdata0->nvars >= 1);
13537  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13538 
13539  /* sort the constraint */
13540  SCIP_CALL( consdataSort(scip, consdata0) );
13541 
13542  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13543  consdataCalcSignatures(consdata0);
13544  possignature0 = consdata0->possignature;
13545  negsignature0 = consdata0->negsignature;
13546 
13547  /* get temporary memory for indices of common variables */
13548  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13549  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13550  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13551  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13552  diffidx1minus0size = consdata0->nvars;
13553 
13554  cons0lhs = consdata0->lhs;
13555  cons0rhs = consdata0->rhs;
13556  cons0upgraded = consdata0->upgraded;
13557 
13558  /* check constraint against all prior constraints */
13559  cons0changed = consdata0->changed;
13560  consdata0->changed = FALSE;
13561  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13562  {
13563  SCIP_CONS* cons1;
13564  SCIP_CONSDATA* consdata1;
13565  uint64_t possignature1;
13566  uint64_t negsignature1;
13567  SCIP_Bool cons0dominateslhs;
13568  SCIP_Bool cons1dominateslhs;
13569  SCIP_Bool cons0dominatesrhs;
13570  SCIP_Bool cons1dominatesrhs;
13571  SCIP_Bool cons1isequality;
13572  SCIP_Bool coefsequal;
13573  SCIP_Bool coefsnegated;
13574  SCIP_Bool tryaggregation;
13575  int nvarscommon;
13576  int nvars0minus1;
13577  int nvars1minus0;
13578  int commonidxweight;
13579  int diffidx0minus1weight;
13580  int diffidx1minus0weight;
13581  int v0;
13582  int v1;
13583 
13584  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13585  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13586  assert(cons0upgraded == consdata0->upgraded);
13587 
13588  cons1 = conss[c];
13589 
13590  /* cons1 has become inactive during presolving of constraint pairs */
13591  if( cons1 == NULL )
13592  continue;
13593 
13594  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13595  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13596 
13597  consdata1 = SCIPconsGetData(cons1);
13598  assert(consdata1 != NULL);
13599 
13600  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13601  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13602  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13603 
13604  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13605  if( !cons0changed && !consdata1->changed )
13606  continue;
13607 
13608  /* if both constraints are already upgraded, skip the pair;
13609  * because changes on these constraints cannot be applied to the instance anymore */
13610  if( cons0upgraded && consdata1->upgraded )
13611  continue;
13612 
13613  assert(consdata1->nvars >= 1);
13614 
13615  /* sort the constraint */
13616  SCIP_CALL( consdataSort(scip, consdata1) );
13617 
13618  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13619  consdataCalcSignatures(consdata1);
13620  possignature1 = consdata1->possignature;
13621  negsignature1 = consdata1->negsignature;
13622 
13623  /* the signatures give a quick test to check for domination and equality of coefficients */
13624  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13625  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13626  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13627  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13628  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13629  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13630  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13631  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13632  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13633  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13634  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13635  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13636  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13637  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13638  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13639  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13640  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13641  && !coefsequal && !coefsnegated && !tryaggregation )
13642  continue;
13643 
13644  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13645  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13646  {
13647  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13648  diffidx1minus0size = consdata1->nvars;
13649  }
13650 
13651  /* check consdata0 against consdata1:
13652  * - if lhs0 >= lhs1 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. left hand side
13654  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13655  * consdata0 dominates consdata1 w.r.t. right hand side
13656  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13657  * ranged row (or equality)
13658  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13659  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13660  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13661  * number of continuous and integer variables are preferred:
13662  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13663  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13664  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13665  * to be positive to not switch the sense of the (in)equality cons0
13666  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13667  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13668  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13669  * to be positive to not switch the sense of the (in)equality cons1
13670  */
13671 
13672  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13673  nvarscommon = 0;
13674  commonidxweight = 0;
13675  nvars0minus1 = 0;
13676  diffidx0minus1weight = 0;
13677  nvars1minus0 = 0;
13678  diffidx1minus0weight = 0;
13679  v0 = 0;
13680  v1 = 0;
13681  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13682  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13683  || coefsequal || coefsnegated || tryaggregation) )
13684  {
13685  SCIP_VAR* var;
13686  SCIP_Real val0;
13687  SCIP_Real val1;
13688  int varcmp;
13689 
13690  /* test, if variable appears in only one or in both constraints */
13691  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13692  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13693  else if( v0 < consdata0->nvars )
13694  varcmp = -1;
13695  else
13696  varcmp = +1;
13697 
13698  switch( varcmp )
13699  {
13700  case -1:
13701  /* variable doesn't appear in consdata1 */
13702  var = consdata0->vars[v0];
13703  val0 = consdata0->vals[v0];
13704  val1 = 0.0;
13705  if( tryaggregation )
13706  {
13707  diffidx0minus1[nvars0minus1] = v0;
13708  nvars0minus1++;
13709  diffidx0minus1weight += getVarWeight(var);
13710  }
13711  v0++;
13712  coefsequal = FALSE;
13713  coefsnegated = FALSE;
13714  break;
13715 
13716  case +1:
13717  /* variable doesn't appear in consdata0 */
13718  var = consdata1->vars[v1];
13719  val0 = 0.0;
13720  val1 = consdata1->vals[v1];
13721  if( tryaggregation )
13722  {
13723  diffidx1minus0[nvars1minus0] = v1;
13724  nvars1minus0++;
13725  diffidx1minus0weight += getVarWeight(var);
13726  }
13727  v1++;
13728  coefsequal = FALSE;
13729  coefsnegated = FALSE;
13730  break;
13731 
13732  case 0:
13733  /* variable appears in both constraints */
13734  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13735  var = consdata0->vars[v0];
13736  val0 = consdata0->vals[v0];
13737  val1 = consdata1->vals[v1];
13738  if( tryaggregation )
13739  {
13740  commonidx0[nvarscommon] = v0;
13741  commonidx1[nvarscommon] = v1;
13742  nvarscommon++;
13743  commonidxweight += getVarWeight(var);
13744  }
13745  v0++;
13746  v1++;
13747  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13748  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13749  break;
13750 
13751  default:
13752  SCIPerrorMessage("invalid comparison result\n");
13753  SCIPABORT();
13754  var = NULL;
13755  val0 = 0.0;
13756  val1 = 0.0;
13757  }
13758  assert(var != NULL);
13759 
13760  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13761  if( SCIPisGT(scip, val0, val1) )
13762  {
13763  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13764  {
13765  cons0dominatesrhs = FALSE;
13766  cons1dominateslhs = FALSE;
13767  }
13768  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13769  {
13770  cons0dominateslhs = FALSE;
13771  cons1dominatesrhs = FALSE;
13772  }
13773  }
13774  else if( SCIPisLT(scip, val0, val1) )
13775  {
13776  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13777  {
13778  cons0dominateslhs = FALSE;
13779  cons1dominatesrhs = FALSE;
13780  }
13781  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13782  {
13783  cons0dominatesrhs = FALSE;
13784  cons1dominateslhs = FALSE;
13785  }
13786  }
13787  }
13788 
13789  /* check for disaggregated ranged rows */
13790  if( coefsequal || coefsnegated )
13791  {
13792  SCIP_CONS* consstay;
13793  SCIP_CONS* consdel;
13794 #ifndef NDEBUG
13795  SCIP_CONSDATA* consdatastay;
13796 #endif
13797  SCIP_CONSDATA* consdatadel;
13798  SCIP_Real lhs;
13799  SCIP_Real rhs;
13800  int consinddel;
13801 
13802  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13803  * best left and right hand sides; delete the old constraints afterwards
13804  */
13805  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13806  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13807  SCIPdebugPrintCons(scip, cons0, NULL);
13808  SCIPdebugPrintCons(scip, cons1, NULL);
13809 
13810  if( coefsequal )
13811  {
13812  /* the coefficients of both rows are equal */
13813  lhs = MAX(consdata0->lhs, consdata1->lhs);
13814  rhs = MIN(consdata0->rhs, consdata1->rhs);
13815  }
13816  else
13817  {
13818  /* the coefficients of both rows are negations */
13819  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13820  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13821  }
13822  if( SCIPisFeasLT(scip, rhs, lhs) )
13823  {
13824  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13825  *cutoff = TRUE;
13826  break;
13827  }
13828 
13829  /* check which constraint has to stay;
13830  * changes applied to an upgraded constraint will not be considered in the instance */
13831  if( consdata0->upgraded )
13832  {
13833  assert(!consdata1->upgraded);
13834  consstay = cons1;
13835 #ifndef NDEBUG
13836  consdatastay = consdata1;
13837 #endif
13838 
13839  consdel = cons0;
13840  consdatadel = consdata0;
13841  consinddel = chkind;
13842  }
13843  else
13844  {
13845  consstay = cons0;
13846 #ifndef NDEBUG
13847  consdatastay = consdata0;
13848 #endif
13849 
13850  consdel = cons1;
13851  consdatadel = consdata1;
13852  consinddel = c;
13853  }
13854 
13855  /* update the sides of consstay */
13856  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13857  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13858  if( !consdata0->upgraded )
13859  {
13860  assert(consstay == cons0);
13861  cons0lhs = consdata0->lhs;
13862  cons0rhs = consdata0->rhs;
13863  }
13864 
13865  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13866  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13867 
13868  assert( !consdatastay->upgraded );
13869  /* delete consdel */
13870  SCIP_CALL( SCIPdelCons(scip, consdel) );
13871  conss[consinddel] = NULL;
13872  if( !consdatadel->upgraded )
13873  (*ndelconss)++;
13874  continue;
13875  }
13876 
13877  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13878  * redundant
13879  */
13880  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13881  {
13882  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13883  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13884  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13885  SCIPdebugPrintCons(scip, cons0, NULL);
13886  SCIPdebugPrintCons(scip, cons1, NULL);
13887 
13888  /* check for infeasibility */
13889  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13890  {
13891  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13892  *cutoff = TRUE;
13893  break;
13894  }
13895 
13896  /* remove redundant left hand side */
13897  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13898  {
13899  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13900  cons0lhs = consdata0->lhs;
13901  cons0isequality = FALSE;
13902  if( !consdata0->upgraded )
13903  {
13904  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13905  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13906 
13907  (*nchgsides)++;
13908  }
13909  }
13910  }
13911  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13912  {
13913  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13914  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13915  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13916  SCIPdebugPrintCons(scip, cons1, NULL);
13917  SCIPdebugPrintCons(scip, cons0, NULL);
13918 
13919  /* check for infeasibility */
13920  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13921  {
13922  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13923  *cutoff = TRUE;
13924  break;
13925  }
13926 
13927  /* remove redundant left hand side */
13928  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13929  {
13930  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13931  cons1isequality = FALSE;
13932  if( !consdata1->upgraded )
13933  {
13934  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13935  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13936 
13937  (*nchgsides)++;
13938  }
13939  }
13940  }
13941  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13942  {
13943  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13944  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13945  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13946  SCIPdebugPrintCons(scip, cons0, NULL);
13947  SCIPdebugPrintCons(scip, cons1, NULL);
13948 
13949  /* check for infeasibility */
13950  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13951  {
13952  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13953  *cutoff = TRUE;
13954  break;
13955  }
13956 
13957  /* remove redundant right hand side */
13958  if( !SCIPisInfinity(scip, consdata0->rhs) )
13959  {
13960  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13961  cons0rhs = consdata0->rhs;
13962  cons0isequality = FALSE;
13963  if( !consdata0->upgraded )
13964  {
13965  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13966  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13967 
13968  (*nchgsides)++;
13969  }
13970  }
13971  }
13972  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13973  {
13974  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13975  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13976  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13977  SCIPdebugPrintCons(scip, cons1, NULL);
13978  SCIPdebugPrintCons(scip, cons0, NULL);
13979 
13980  /* check for infeasibility */
13981  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13982  {
13983  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13984  *cutoff = TRUE;
13985  break;
13986  }
13987 
13988  /* remove redundant right hand side */
13989  if( !SCIPisInfinity(scip, consdata1->rhs) )
13990  {
13991  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13992  cons1isequality = FALSE;
13993  if( !consdata1->upgraded )
13994  {
13995  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13996  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13997 
13998  (*nchgsides)++;
13999  }
14000  }
14001  }
14002 
14003  /* check for now redundant constraints */
14004  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
14005  {
14006  /* consdata0 became redundant */
14007  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
14008  SCIP_CALL( SCIPdelCons(scip, cons0) );
14009  conss[chkind] = NULL;
14010  if( !consdata0->upgraded )
14011  {
14012  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14013  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
14014 
14015  (*ndelconss)++;
14016  }
14017  continue;
14018  }
14019  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
14020  {
14021  /* consdata1 became redundant */
14022  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
14023  SCIP_CALL( SCIPdelCons(scip, cons1) );
14024  conss[c] = NULL;
14025  if( !consdata1->upgraded )
14026  {
14027  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
14028  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
14029 
14030  (*ndelconss)++;
14031  }
14032  continue;
14033  }
14034 
14035  /* check, if we want to aggregate an (in)equality with an equality:
14036  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
14037  */
14038  if( tryaggregation )
14039  {
14040  SCIP_Bool aggregated;
14041 
14042  assert(consdata0->nvars == nvarscommon + nvars0minus1);
14043  assert(consdata1->nvars == nvarscommon + nvars1minus0);
14044 
14045  aggregated = FALSE;
14046  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
14047  {
14048  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
14049  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
14050  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
14051  nchgcoefs, &aggregated, cutoff) );
14052 
14053  if( *cutoff )
14054  break;
14055 
14056  /* update array of active constraints */
14057  if( aggregated )
14058  {
14059  assert(!SCIPconsIsActive(cons0));
14060  assert(SCIPconsIsActive(cons1));
14061  conss[chkind] = NULL;
14062  }
14063  }
14064  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
14065  {
14066  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
14067  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
14068  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
14069  nchgcoefs, &aggregated, cutoff) );
14070 
14071  if( *cutoff )
14072  break;
14073 
14074  /* update array of active constraints */
14075  if( aggregated )
14076  {
14077  assert(!SCIPconsIsActive(cons1));
14078  assert(SCIPconsIsActive(cons0));
14079  conss[c] = NULL;
14080  }
14081  }
14082  }
14083  }
14084 
14085  /* free temporary memory */
14086  SCIPfreeBufferArray(scip, &diffidx1minus0);
14087  SCIPfreeBufferArray(scip, &diffidx0minus1);
14088  SCIPfreeBufferArray(scip, &commonidx1);
14089  SCIPfreeBufferArray(scip, &commonidx0);
14090 
14091  return SCIP_OKAY;
14092 }
14093 
14094 /** do stuffing presolving on a single constraint */
14095 static
14097  SCIP* scip, /**< SCIP data structure */
14098  SCIP_CONS* cons, /**< linear constraint */
14099  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
14100  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
14101  * constraints using the cheapest variable? */
14102  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14103  int* nfixedvars, /**< pointer to count the total number of fixed variables */
14104  int* nchgbds /**< pointer to count the total number of tightened bounds */
14105  )
14106 {
14107  SCIP_CONSDATA* consdata;
14108  SCIP_Real* ratios;
14109  int* varpos;
14110  SCIP_Bool* swapped;
14111  SCIP_VAR** vars;
14112  SCIP_Real* vals;
14113  SCIP_VAR* var;
14114  SCIP_Real lb;
14116  SCIP_Real minactivity;
14117  SCIP_Real maxactivity;
14118  SCIP_Real maxcondactivity;
14119  SCIP_Real mincondactivity;
14120  SCIP_Real rhs;
14121  SCIP_Real val;
14122  SCIP_Real obj;
14123  SCIP_Real factor;
14124  SCIP_Bool minactisrelax;
14125  SCIP_Bool maxactisrelax;
14126  SCIP_Bool isminsettoinfinity;
14127  SCIP_Bool ismaxsettoinfinity;
14128  SCIP_Bool tryfixing;
14129  int nsingletons;
14130  int idx;
14131  int v;
14132  int nvars;
14133 
14134  assert(scip != NULL);
14135  assert(cons != NULL);
14136  assert(nfixedvars != NULL);
14137 
14138  consdata = SCIPconsGetData(cons);
14139 
14140  /* we only want to run for inequalities */
14141  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14142  return SCIP_OKAY;
14143 
14144  if( singlevarstuffing )
14145  {
14146  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14147  &isminsettoinfinity, &ismaxsettoinfinity);
14148  }
14149  else
14150  {
14151  minactivity = SCIP_INVALID;
14152  maxactivity = SCIP_INVALID;
14153  isminsettoinfinity = FALSE;
14154  ismaxsettoinfinity = FALSE;
14155  }
14156 
14157  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14158  * the new maxactivity is minus the old minactivity then
14159  */
14160  if( SCIPisInfinity(scip, consdata->rhs) )
14161  {
14162  rhs = -consdata->lhs;
14163  factor = -1.0;
14164  maxactivity = -minactivity;
14165  ismaxsettoinfinity = isminsettoinfinity;
14166  }
14167  else
14168  {
14169  assert(SCIPisInfinity(scip, -consdata->lhs));
14170  rhs = consdata->rhs;
14171  factor = 1.0;
14172  }
14173 
14174  nvars = consdata->nvars;
14175  vars = consdata->vars;
14176  vals = consdata->vals;
14177 
14178  /* check for continuous singletons */
14179  if( singletonstuffing )
14180  {
14181  for( v = 0; v < nvars; ++v )
14182  {
14183  var = vars[v];
14184 
14187  break;
14188  }
14189  }
14190  else
14191  /* we don't want to go into the next block */
14192  v = nvars;
14193 
14194  /* a singleton was found -> perform singleton variable stuffing */
14195  if( v < nvars )
14196  {
14197  assert(singletonstuffing);
14198 
14199  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14200  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14201  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14202 
14203  tryfixing = TRUE;
14204  nsingletons = 0;
14205  mincondactivity = 0.0;
14206  maxcondactivity = 0.0;
14207 
14208  for( v = 0; v < nvars; ++v )
14209  {
14210  var = vars[v];
14211  lb = SCIPvarGetLbGlobal(var);
14212  ub = SCIPvarGetUbGlobal(var);
14213  obj = SCIPvarGetObj(var);
14214  val = factor * vals[v];
14215 
14216  assert(!SCIPisZero(scip, val));
14217 
14218  /* the variable is a singleton and continuous */
14221  {
14222  if( SCIPisNegative(scip, obj) && val > 0 )
14223  {
14224  /* case 1: obj < 0 and coef > 0 */
14225  if( SCIPisInfinity(scip, -lb) )
14226  {
14227  tryfixing = FALSE;
14228  break;
14229  }
14230 
14231  maxcondactivity += val * lb;
14232  mincondactivity += val * lb;
14233  swapped[v] = FALSE;
14234  ratios[nsingletons] = obj / val;
14235  varpos[nsingletons] = v;
14236  nsingletons++;
14237  }
14238  else if( SCIPisPositive(scip, obj) && val < 0 )
14239  {
14240  /* case 2: obj > 0 and coef < 0 */
14241  if( SCIPisInfinity(scip, ub) )
14242  {
14243  tryfixing = FALSE;
14244  break;
14245  }
14246  /* multiply column by (-1) to become case 1.
14247  * now bounds are swapped: ub := -lb, lb := -ub
14248  */
14249 
14250  maxcondactivity += val * ub;
14251  mincondactivity += val * ub;
14252  swapped[v] = TRUE;
14253  ratios[nsingletons] = obj / val;
14254  varpos[nsingletons] = v;
14255  nsingletons++;
14256  }
14257  else if( val > 0 )
14258  {
14259  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14260  * we only consider the lower bound for the constants
14261  */
14262  assert(!SCIPisNegative(scip, obj));
14263 
14264  if( SCIPisInfinity(scip, -lb) )
14265  {
14266  /* maybe unbounded */
14267  tryfixing = FALSE;
14268  break;
14269  }
14270 
14271  maxcondactivity += val * lb;
14272  mincondactivity += val * lb;
14273  }
14274  else
14275  {
14276  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14277  * we only consider the upper bound for the constants
14278  */
14279  assert(!SCIPisPositive(scip, obj));
14280  assert(val < 0);
14281 
14282  if( SCIPisInfinity(scip, ub) )
14283  {
14284  /* maybe unbounded */
14285  tryfixing = FALSE;
14286  break;
14287  }
14288 
14289  maxcondactivity += val * ub;
14290  mincondactivity += val * ub;
14291  }
14292  }
14293  else
14294  {
14295  /* consider contribution of discrete variables, non-singleton
14296  * continuous variables and variables with more than one lock
14297  */
14298  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14299  {
14300  tryfixing = FALSE;
14301  break;
14302  }
14303 
14304  if( val > 0 )
14305  {
14306  maxcondactivity += val * ub;
14307  mincondactivity += val * lb;
14308  }
14309  else
14310  {
14311  maxcondactivity += val * lb;
14312  mincondactivity += val * ub;
14313  }
14314  }
14315  }
14316  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14317  {
14318  SCIP_Real delta;
14319  SCIP_Bool tightened;
14320 #ifdef SCIP_DEBUG
14321  int oldnfixedvars = *nfixedvars;
14322  int oldnchgbds = *nchgbds;
14323 #endif
14324 
14325  SCIPsortRealInt(ratios, varpos, nsingletons);
14326 
14327  /* verify which singleton continuous variables can be fixed */
14328  for( v = 0; v < nsingletons; ++v )
14329  {
14330  idx = varpos[v];
14331  var = vars[idx];
14332  val = factor * vals[idx];
14333  lb = SCIPvarGetLbGlobal(var);
14334  ub = SCIPvarGetUbGlobal(var);
14335 
14336  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14337  assert((val < 0) == swapped[idx]);
14338  val = REALABS(val);
14339 
14340  /* stop fixing if variable bounds are not finite */
14341  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14342  break;
14343 
14346  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14347 
14348  /* calculate the change in the row activities if this variable changes
14349  * its value from its worst to its best bound
14350  */
14351  if( swapped[idx] )
14352  delta = -(lb - ub) * val;
14353  else
14354  delta = (ub - lb) * val;
14355 
14356  assert(!SCIPisNegative(scip, delta));
14357 
14358  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14359  {
14360  if( swapped[idx] )
14361  {
14362  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14363  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14364  }
14365  else
14366  {
14367  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14368  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14369  }
14370 
14371  if( *cutoff )
14372  break;
14373  if( tightened )
14374  {
14375  (*nfixedvars)++;
14376  }
14377  }
14378  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14379  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14380  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14381  * troubles in case of large bounds.
14382  */
14383  else if( SCIPisLE(scip, rhs, mincondactivity) )
14384  {
14385  if( swapped[idx] )
14386  {
14387  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14388  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14389  }
14390  else
14391  {
14392  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14393  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14394  }
14395 
14396  if( *cutoff )
14397  break;
14398  if( tightened )
14399  {
14400  (*nfixedvars)++;
14401  }
14402  }
14403 
14404  maxcondactivity += delta;
14405  mincondactivity += delta;
14406  }
14407 
14408 #ifdef SCIP_DEBUG
14409  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14410  {
14411  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14412  }
14413 #endif
14414  }
14415 
14416  SCIPfreeBufferArray(scip, &swapped);
14417  SCIPfreeBufferArray(scip, &ratios);
14418  SCIPfreeBufferArray(scip, &varpos);
14419  }
14420 
14421  /* perform single-variable stuffing:
14422  * for a linear inequality
14423  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14424  * with a_i > 0 and objective coefficients c_i < 0,
14425  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14426  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14427  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14428  * is redundant.
14429  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14430  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14431  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14432  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14433  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14434  * upper bound.
14435  * Note that the others variables may have downlocks from other constraints, which we do not need to care
14436  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14437  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14438  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14439  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14440  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14441  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14442  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14443  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14444  * c_k * ceil((maxactivity - rhs)/val) is still better than
14445  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14446  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14447  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14448  * sign of coefficients in constraint and objective prevent the use of this method.
14449  */
14450  if( singlevarstuffing && !ismaxsettoinfinity )
14451  {
14452  SCIP_Real bestratio = -SCIPinfinity(scip);
14453  SCIP_Real secondbestratio = -SCIPinfinity(scip);
14454  SCIP_Real ratio;
14455  int bestindex = -1;
14456  int bestuplocks = 0;
14457  int bestdownlocks = 1;
14458  int downlocks;
14459  int uplocks;
14460  SCIPdebug( int oldnfixedvars = *nfixedvars; )
14461  SCIPdebug( int oldnchgbds = *nchgbds; )
14462 
14463  /* loop over all variables to identify the best and second-best ratio */
14464  for( v = 0; v < nvars; ++v )
14465  {
14466  var = vars[v];
14467  obj = SCIPvarGetObj(var);
14468  val = factor * vals[v];
14469 
14470  assert(!SCIPisZero(scip, val));
14471 
14472  ratio = obj / val;
14473 
14474  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14475  if( !SCIPisNegative(scip, ratio) )
14476  {
14477  bestindex = -1;
14478  break;
14479  }
14480 
14481  if( val > 0 )
14482  {
14485  }
14486  else
14487  {
14488  downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14490  }
14491 
14492  /* better ratio, update best candidate
14493  * @todo use some tolerance
14494  * @todo check size of domain and updated ratio for integer variables already?
14495  */
14496  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14497  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14498  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14499  {
14500  /* best index becomes second-best*/
14501  if( bestindex != -1 )
14502  {
14503  /* second-best index must not have more than 1 uplock */
14504  if( bestuplocks > 1 )
14505  {
14506  bestindex = -1;
14507  break;
14508  }
14509  else
14510  {
14511  secondbestratio = bestratio;
14512  }
14513  }
14514  bestdownlocks = downlocks;
14515  bestuplocks = uplocks;
14516  bestratio = ratio;
14517  bestindex = v;
14518 
14519  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14520  * if it is not the best, it has too many uplocks -> not applicable
14521  */
14522  if( bestdownlocks > 0 && bestuplocks > 1 )
14523  {
14524  bestindex = -1;
14525  break;
14526  }
14527  }
14528  else
14529  {
14530  /* non-best index must not have more than 1 uplock */
14531  if( uplocks > 1 )
14532  {
14533  bestindex = -1;
14534  break;
14535  }
14536  /* update second-best ratio */
14537  if( ratio > secondbestratio )
14538  {
14539  secondbestratio = ratio;
14540  }
14541  }
14542  }
14543 
14544  /* check if we can apply single variable stuffing */
14545  if( bestindex != -1 && bestdownlocks == 0 )
14546  {
14547  SCIP_Bool tightened = FALSE;
14548  SCIP_Real bounddelta;
14549 
14550  var = vars[bestindex];
14551  obj = SCIPvarGetObj(var);
14552  val = factor * vals[bestindex];
14553  lb = SCIPvarGetLbGlobal(var);
14554  ub = SCIPvarGetUbGlobal(var);
14555  tryfixing = TRUE;
14556 
14557  if( val < 0 )
14558  {
14559  assert(!SCIPisNegative(scip, obj));
14560 
14561  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14562  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14563  {
14564  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14565  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14566  assert(SCIPisPositive(scip, activitydelta));
14567 
14568  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14569 
14570  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14571  assert(SCIPisPositive(scip, bounddelta));
14572  }
14573  else
14574  bounddelta = (maxactivity - rhs)/-val;
14575 
14576  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14577 
14578  if( tryfixing )
14579  {
14580  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14581 
14582  if( SCIPisEQ(scip, lb + bounddelta, ub) )
14583  {
14584  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14585  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14586  }
14587  else
14588  {
14589  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14590  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14591  }
14592  }
14593  }
14594  else
14595  {
14596  assert(!SCIPisPositive(scip, obj));
14597 
14598  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14599  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14600  {
14601  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14602  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14603  assert(SCIPisPositive(scip, activitydelta));
14604 
14605  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14606 
14607  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14608  assert(SCIPisPositive(scip, bounddelta));
14609  }
14610  else
14611  bounddelta = (maxactivity - rhs)/val;
14612 
14613  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14614 
14615  if( tryfixing )
14616  {
14617  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14618 
14619  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14620  {
14621  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14622  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14623  }
14624  else
14625  {
14626  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14627  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14628  }
14629  }
14630  }
14631 
14632  if( *cutoff )
14633  return SCIP_OKAY;
14634  if( tightened )
14635  {
14636  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14637  ++(*nfixedvars);
14638  else
14639  ++(*nchgbds);
14640 
14641  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14642  for( v = 0; v < nvars; ++v )
14643  {
14644  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14645  SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14648  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14649  }
14650  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14651 
14652  for( v = 0; v < nvars; ++v )
14653  {
14654  if( v == bestindex )
14655  continue;
14656 
14657  if( factor * vals[v] < 0 )
14658  {
14659  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14660  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14661  SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14662  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14663  }
14664  else
14665  {
14666  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14667  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14668  SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14669  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14670  }
14671 
14672  if( *cutoff )
14673  return SCIP_OKAY;
14674  if( tightened )
14675  ++(*nfixedvars);
14676  }
14677  SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14678  }
14679  }
14680  }
14681 
14682  return SCIP_OKAY;
14683 }
14684 
14685 /** applies full dual presolving on variables that only appear in linear constraints */
14686 static
14688  SCIP* scip, /**< SCIP data structure */
14689  SCIP_CONS** conss, /**< constraint set */
14690  int nconss, /**< number of constraints */
14691  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14692  int* nchgbds /**< pointer to count the number of bound changes */
14693  )
14694 {
14695  SCIP_Real* redlb;
14696  SCIP_Real* redub;
14697  int* nlocksdown;
14698  int* nlocksup;
14699  SCIP_Bool* isimplint;
14700  SCIP_VAR** origvars;
14701  SCIP_VAR** vars;
14702  SCIP_VAR** conscontvars;
14703  int nvars;
14704  int nbinvars;
14705  int nintvars;
14706  int ncontvars;
14707  int v;
14708  int c;
14709 
14710  /* we calculate redundancy bounds with the following meaning:
14711  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14712  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14713  * then:
14714  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14715  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14716  */
14717 
14718  /* Additionally, we detect continuous variables that are implicitly integral.
14719  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14720  * and all constraints (including the bounds as trivial constraints) in which:
14721  * c_j > 0: the variable is down-locked,
14722  * c_j < 0: the variable is up-locked,
14723  * c_j = 0: the variable appears
14724  * have, apart from j, only integer variables with integral coefficients and integral sides.
14725  * This is because then, the value of the variable is either determined by one of its bounds or
14726  * by one of these constraints, and in all cases, the value of the variable is integral.
14727  */
14728 
14729  assert(scip != NULL);
14730  assert(nconss == 0 || conss != NULL);
14731  assert(nchgbds != NULL);
14732  assert(!SCIPinProbing(scip));
14733 
14734  /* get active variables */
14735  nvars = SCIPgetNVars(scip);
14736  origvars = SCIPgetVars(scip);
14737 
14738  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14739  nbinvars = SCIPgetNBinVars(scip);
14740  if( nbinvars == nvars )
14741  return SCIP_OKAY;
14742 
14743  /* get number of continuous variables */
14744  ncontvars = SCIPgetNContVars(scip);
14745  nintvars = nvars - ncontvars;
14746 
14747  /* copy the variable array since this array might change during the curse of this algorithm */
14748  nvars = nvars - nbinvars;
14749  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14750 
14751  /* allocate temporary memory */
14752  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14753  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14754  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14755  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14756  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14757  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14758 
14759  /* initialize redundancy bounds */
14760  for( v = 0; v < nvars; ++v )
14761  {
14762  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14763  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14764  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14765  }
14766  BMSclearMemoryArray(nlocksdown, nvars);
14767  BMSclearMemoryArray(nlocksup, nvars);
14768 
14769  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14770  * We better not use SCIPisFeasIntegral() in these checks.
14771  */
14772  for( v = 0; v < ncontvars; v++ )
14773  {
14774  SCIP_VAR* var;
14775  SCIP_Real obj;
14776  SCIP_Real lb;
14777  SCIP_Real ub;
14778 
14779  var = vars[v + nintvars - nbinvars];
14780  lb = SCIPvarGetLbGlobal(var);
14781  ub = SCIPvarGetUbGlobal(var);
14782 
14783  obj = SCIPvarGetObj(var);
14784  if( SCIPisZero(scip, obj) )
14785  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14786  else
14787  {
14788  if( SCIPisPositive(scip, obj) )
14789  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14790  else
14791  {
14792  assert(SCIPisNegative(scip, obj));
14793  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14794  }
14795  }
14796  }
14797 
14798  /* scan all constraints */
14799  for( c = 0; c < nconss; ++c )
14800  {
14801  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14802  * part of checked disjunctions)
14803  */
14804  if( SCIPconsIsLocked(conss[c]) )
14805  {
14806  SCIP_CONSDATA* consdata;
14807  SCIP_Bool lhsexists;
14808  SCIP_Bool rhsexists;
14809  SCIP_Bool hasimpliedpotential;
14810  SCIP_Bool integralcoefs;
14811  int nlockspos;
14812  int contvarpos;
14813  int nconscontvars;
14814  int i;
14815 
14816  consdata = SCIPconsGetData(conss[c]);
14817  assert(consdata != NULL);
14818 
14819  /* get number of times the constraint was locked */
14820  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14821 
14822  /* we do not want to include constraints with locked negation (this would be too weird) */
14823  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14824  {
14825  /* mark all continuous variables as not being implicit integral */
14826  for( i = 0; i < consdata->nvars; ++i )
14827  {
14828  SCIP_VAR* var;
14829 
14830  var = consdata->vars[i];
14832  {
14833  int contv;
14834  contv = SCIPvarGetProbindex(var) - nintvars;
14835  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14836  isimplint[contv] = FALSE;
14837  }
14838  }
14839  continue;
14840  }
14841 
14842  /* check for existing sides */
14843  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14844  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14845 
14846  /* count locks and update redundancy bounds */
14847  contvarpos = -1;
14848  nconscontvars = 0;
14849  hasimpliedpotential = FALSE;
14850  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14851 
14852  for( i = 0; i < consdata->nvars; ++i )
14853  {
14854  SCIP_VAR* var;
14855  SCIP_Real val;
14856  SCIP_Real minresactivity;
14857  SCIP_Real maxresactivity;
14858  SCIP_Real newredlb;
14859  SCIP_Real newredub;
14860  SCIP_Bool minisrelax;
14861  SCIP_Bool maxisrelax;
14862  SCIP_Bool isminsettoinfinity;
14863  SCIP_Bool ismaxsettoinfinity;
14864  int arrayindex;
14865 
14866  var = consdata->vars[i];
14867  val = consdata->vals[i];
14868 
14869  /* check if still all integer variables have integral coefficients */
14870  if( SCIPvarIsIntegral(var) )
14871  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14872 
14873  /* we do not need to process binary variables */
14874  if( SCIPvarIsBinary(var) )
14875  continue;
14876 
14877  if( SCIPconsIsModifiable(conss[c]) )
14878  {
14879  minresactivity = -SCIPinfinity(scip);
14880  maxresactivity = SCIPinfinity(scip);
14881  isminsettoinfinity = TRUE;
14882  ismaxsettoinfinity = TRUE;
14883  }
14884  else
14885  {
14886  /* calculate residual activity bounds if variable would be fixed to zero */
14887  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14888  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14889 
14890  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14891  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14892  * This is needed, because we do not want to rely on relaxed finite resactivities.
14893  */
14894  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14895 
14896  /* check minresactivity for reliability */
14897  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14898  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14899 
14900  /* check maxresactivity for reliability */
14901  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14902  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14903  }
14904 
14905  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14906 
14907  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14908 
14909  newredlb = redlb[arrayindex];
14910  newredub = redub[arrayindex];
14911  if( val > 0.0 )
14912  {
14913  if( lhsexists )
14914  {
14915  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14916  nlocksdown[arrayindex] += nlockspos;
14917  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14918  }
14919  if( rhsexists )
14920  {
14921  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14922  nlocksup[arrayindex] += nlockspos;
14923  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14924  }
14925  }
14926  else
14927  {
14928  if( lhsexists )
14929  {
14930  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14931  nlocksup[arrayindex] += nlockspos;
14932  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14933  }
14934  if( rhsexists )
14935  {
14936  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14937  nlocksdown[arrayindex] += nlockspos;
14938  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14939  }
14940  }
14941 
14942  /* if the variable is integer, we have to round the value to the next integral value */
14943  if( SCIPvarIsIntegral(var) )
14944  {
14945  if( !SCIPisInfinity(scip, newredlb) )
14946  newredlb = SCIPceil(scip, newredlb);
14947  if( !SCIPisInfinity(scip, -newredub) )
14948  newredub = SCIPfloor(scip, newredub);
14949  }
14950 
14951  /* update redundancy bounds */
14952  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14953  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14954 
14955  /* collect the continuous variables of the constraint */
14957  {
14958  int contv;
14959 
14960  assert(nconscontvars < ncontvars);
14961  contvarpos = i;
14962  conscontvars[nconscontvars] = var;
14963  nconscontvars++;
14964 
14965  contv = SCIPvarGetProbindex(var) - nintvars;
14966  assert(0 <= contv && contv < ncontvars);
14967  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14968  }
14969  }
14970 
14971  /* update implied integer status of continuous variables */
14972  if( hasimpliedpotential )
14973  {
14974  if( nconscontvars > 1 || !integralcoefs )
14975  {
14976  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14977  * none of the continuous variables is implied integer
14978  */
14979  for( i = 0; i < nconscontvars; i++ )
14980  {
14981  int contv;
14982  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14983  assert(0 <= contv && contv < ncontvars);
14984  isimplint[contv] = FALSE;
14985  }
14986  }
14987  else
14988  {
14989  SCIP_VAR* var;
14990  SCIP_Real val;
14991  SCIP_Real absval;
14992  int contv;
14993 
14994  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14995  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14996  * side(s) of the constraint is integral
14997  */
14998  assert(nconscontvars == 1);
14999  assert(0 <= contvarpos && contvarpos < consdata->nvars);
15000  var = consdata->vars[contvarpos];
15001  val = consdata->vals[contvarpos];
15002  contv = SCIPvarGetProbindex(var) - nintvars;
15003  assert(0 <= contv && contv < ncontvars);
15004  assert(isimplint[contv]);
15005 
15006  absval = REALABS(val);
15007  if( !SCIPisEQ(scip, absval, 1.0) )
15008  isimplint[contv] = FALSE;
15009  else
15010  {
15011  SCIP_Real obj;
15012 
15013  obj = SCIPvarGetObj(var);
15014  if( obj * val >= 0.0 && lhsexists )
15015  {
15016  /* the variable may be blocked by the constraint's left hand side */
15017  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
15018  }
15019  if( obj * val <= 0.0 && rhsexists )
15020  {
15021  /* the variable may be blocked by the constraint's left hand side */
15022  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
15023  }
15024  }
15025  }
15026  }
15027  }
15028  }
15029 
15030  /* check if any bounds can be tightened due to optimality */
15031  for( v = 0; v < nvars; ++v )
15032  {
15033  SCIP_VAR* var;
15034  SCIP_Real obj;
15035  SCIP_Bool infeasible;
15036  SCIP_Bool tightened;
15037 
15038  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
15039  assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15040  assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15041 
15042  var = vars[v];
15043  obj = SCIPvarGetObj(var);
15044  if( obj >= 0.0 )
15045  {
15046  /* making the variable as small as possible does not increase the objective:
15047  * check if all down locks of the variables are due to linear constraints;
15048  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
15049  */
15050  if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15051  && !SCIPisInfinity(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( obj <= 0.0 )
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 smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
15076  */
15077  if( SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
15078  && !SCIPisInfinity(scip, redub[v])
15079  && redub[v] > SCIPvarGetLbGlobal(var) )
15080  {
15081  SCIP_Real lb;
15082 
15083  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
15084  * -> tighten lower bound to x_v >= redub[v]
15085  */
15086  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
15088  redub[v]);
15089  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
15090  assert(!infeasible);
15091 
15092  lb = SCIPvarGetLbGlobal(var);
15093  redlb[v] = MAX(redlb[v], lb);
15094  if( tightened )
15095  (*nchgbds)++;
15096  }
15097  }
15098  }
15099 
15100  /* upgrade continuous variables to implied integers */
15101  for( v = nintvars - nbinvars; v < nvars; ++v )
15102  {
15103  SCIP_VAR* var;
15104  SCIP_Bool infeasible;
15105 
15106  var = vars[v];
15107  assert(var != NULL);
15108 
15109  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
15110  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
15111  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
15112  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
15113 
15114  /* we can only conclude implied integrality if the variable appears in no other constraint */
15115  if( isimplint[v - nintvars + nbinvars]
15116  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15117  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15118  {
15119  /* since we locally copied the variable array we can change the variable type immediately */
15120  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15121 
15122  if( infeasible )
15123  {
15124  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15125  *cutoff = TRUE;
15126 
15127  break;
15128  }
15129 
15130  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15132  }
15133  }
15134 
15135  /* free temporary memory */
15136  SCIPfreeBufferArray(scip, &conscontvars);
15137  SCIPfreeBufferArray(scip, &isimplint);
15138  SCIPfreeBufferArray(scip, &nlocksup);
15139  SCIPfreeBufferArray(scip, &nlocksdown);
15140  SCIPfreeBufferArray(scip, &redub);
15141  SCIPfreeBufferArray(scip, &redlb);
15142 
15143  SCIPfreeBufferArray(scip, &vars);
15144 
15145  return SCIP_OKAY;
15146 }
15147 
15148 /** helper function to enforce constraints */
15149 static
15151  SCIP* scip, /**< SCIP data structure */
15152  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
15153  SCIP_CONS** conss, /**< constraints to process */
15154  int nconss, /**< number of constraints */
15155  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
15156  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
15157  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
15158  )
15159 {
15160  SCIP_CONSHDLRDATA* conshdlrdata;
15161  SCIP_Bool checkrelmaxabs;
15162  SCIP_Bool violated;
15163  SCIP_Bool cutoff = FALSE;
15164  int c;
15165 
15166  assert(scip != NULL);
15167  assert(conshdlr != NULL);
15168  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15169  assert(result != NULL);
15170 
15171  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15172  assert(conshdlrdata != NULL);
15173 
15174  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15175 
15176  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15177 
15178  /* check for violated constraints
15179  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15180  */
15181  *result = SCIP_FEASIBLE;
15182 
15183  /* check all useful linear constraints for feasibility */
15184  for( c = 0; c < nusefulconss; ++c )
15185  {
15186  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15187 
15188  if( violated )
15189  {
15190  /* insert LP row as cut */
15191  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15192  if ( cutoff )
15193  *result = SCIP_CUTOFF;
15194  else
15195  *result = SCIP_SEPARATED;
15196  }
15197  }
15198 
15199  /* check all obsolete linear constraints for feasibility */
15200  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15201  {
15202  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15203 
15204  if( violated )
15205  {
15206  /* insert LP row as cut */
15207  SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15208  if ( cutoff )
15209  *result = SCIP_CUTOFF;
15210  else
15211  *result = SCIP_SEPARATED;
15212  }
15213  }
15214 
15215  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15216 
15217  return SCIP_OKAY;
15218 }
15219 
15220 /*
15221  * Callback methods of constraint handler
15222  */
15223 
15224 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15225 static
15226 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15227 { /*lint --e{715}*/
15228  assert(scip != NULL);
15229  assert(conshdlr != NULL);
15230  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15231 
15232  /* call inclusion method of constraint handler */
15234 
15235  *valid = TRUE;
15236 
15237  return SCIP_OKAY;
15238 }
15239 
15240 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15241 static
15242 SCIP_DECL_CONSFREE(consFreeLinear)
15243 { /*lint --e{715}*/
15244  SCIP_CONSHDLRDATA* conshdlrdata;
15246  assert(scip != NULL);
15247  assert(conshdlr != NULL);
15248  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15249 
15250  /* free constraint handler data */
15251  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15252  assert(conshdlrdata != NULL);
15253 
15254  conshdlrdataFree(scip, &conshdlrdata);
15255 
15256  SCIPconshdlrSetData(conshdlr, NULL);
15257 
15258  return SCIP_OKAY;
15259 }
15260 
15262 /** initialization method of constraint handler (called after problem was transformed) */
15263 static
15264 SCIP_DECL_CONSINIT(consInitLinear)
15265 {
15266  SCIP_CONSHDLRDATA* conshdlrdata;
15267  int c;
15268 
15269  assert(scip != NULL);
15270 
15271  /* check for event handler */
15272  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15273  assert(conshdlrdata != NULL);
15274  assert(conshdlrdata->eventhdlr != NULL);
15275  assert(nconss == 0 || conss != NULL);
15276 
15277  conshdlrdata->naddconss = 0;
15278 
15279  /* catch events for the constraints */
15280  for( c = 0; c < nconss; ++c )
15281  {
15282  /* catch all events */
15283  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15284  }
15285 
15286  return SCIP_OKAY;
15287 }
15288 
15289 
15290 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15291 static
15292 SCIP_DECL_CONSEXIT(consExitLinear)
15293 {
15294  SCIP_CONSHDLRDATA* conshdlrdata;
15295  int c;
15296 
15297  assert(scip != NULL);
15298 
15299  /* check for event handler */
15300  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15301  assert(conshdlrdata != NULL);
15302  assert(conshdlrdata->eventhdlr != NULL);
15303 
15304  /* drop events for the constraints */
15305  for( c = nconss - 1; c >= 0; --c )
15306  {
15307  SCIP_CONSDATA* consdata;
15308 
15309  consdata = SCIPconsGetData(conss[c]);
15310  assert(consdata != NULL);
15312  if( consdata->eventdata != NULL )
15313  {
15314  /* drop all events */
15315  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15316  assert(consdata->eventdata == NULL);
15317  }
15318  }
15319 
15320  return SCIP_OKAY;
15321 }
15322 
15323 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15324 static
15326  SCIP* scip, /**< SCIP data structure */
15327  SCIP_Real lhs, /**< left hand side */
15328  SCIP_Real rhs /**< right hand side */
15329  )
15330 {
15331  assert(scip != NULL);
15332 
15333  return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15334 }
15335 
15336 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15337 static
15339  SCIP* scip, /**< SCIP data structure */
15340  SCIP_Real x /**< value */
15341  )
15342 {
15343  assert(scip != NULL);
15345  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15346 }
15347 
15348 /** performs linear constraint type classification as used for MIPLIB
15349  *
15350  * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15351  *
15352  * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15353  * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15354  * Similarly, if specialized constraints were created through the API, these are currently not present.
15355  */
15357  SCIP* scip, /**< SCIP data structure */
15358  SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */
15359  )
15360 {
15361  int c;
15362  SCIP_CONSHDLR* conshdlr;
15363  SCIP_CONS** conss;
15364  int nconss;
15365 
15366  assert(scip != NULL);
15367  assert(linconsstats != NULL);
15368  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15369  assert(conshdlr != NULL);
15370 
15371  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15372  {
15373  conss = SCIPgetConss(scip);
15374  nconss = SCIPgetNConss(scip);
15375  }
15376  else
15377  {
15378  conss = SCIPconshdlrGetConss(conshdlr);
15379  nconss = SCIPconshdlrGetNConss(conshdlr);
15380  }
15381 
15382  /* reset linear constraint type classification */
15383  SCIPlinConsStatsReset(linconsstats);
15384 
15385  /* loop through all constraints */
15386  for( c = 0; c < nconss; c++ )
15387  {
15388  SCIP_CONS* cons;
15389  SCIP_CONSDATA* consdata;
15390  SCIP_Real lhs;
15391  SCIP_Real rhs;
15392  int i;
15393 
15394  /* get constraint */
15395  cons = conss[c];
15396  assert(cons != NULL);
15397 
15398  /* skip constraints that are not handled by the constraint handler */
15399  if( SCIPconsGetHdlr(cons) != conshdlr )
15400  continue;
15401 
15402  /* get constraint data */
15403  consdata = SCIPconsGetData(cons);
15404  assert(consdata != NULL);
15405  rhs = consdata->rhs;
15406  lhs = consdata->lhs;
15407 
15408  /* merge multiples and delete variables with zero coefficient */
15409  SCIP_CALL( mergeMultiples(scip, cons) );
15410  for( i = 0; i < consdata->nvars; i++ )
15411  {
15412  assert(!SCIPisZero(scip, consdata->vals[i]));
15413  }
15414 
15415  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15416  if( consdata->nvars == 0 )
15417  {
15418  SCIPdebugMsg(scip, "classified as EMPTY: ");
15419  SCIPdebugPrintCons(scip, cons, NULL);
15421 
15422  continue;
15423  }
15424 
15425  /* is constraint of type SCIP_CONSTYPE_FREE? */
15426  if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15427  {
15428  SCIPdebugMsg(scip, "classified as FREE: ");
15429  SCIPdebugPrintCons(scip, cons, NULL);
15431 
15432  continue;
15433  }
15434 
15435  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15436  if( consdata->nvars == 1 )
15437  {
15438  SCIPdebugMsg(scip, "classified as SINGLETON: ");
15439  SCIPdebugPrintCons(scip, cons, NULL);
15440  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15441 
15442  continue;
15443  }
15444 
15445  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15446  if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15447  {
15448  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15449  SCIPdebugPrintCons(scip, cons, NULL);
15451 
15452  continue;
15453  }
15454 
15455  /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15456  if( consdata->nvars == 2 )
15457  {
15458  SCIP_LINCONSTYPE constype;
15459 
15460  /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15461  if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15462  && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15463  {
15464  constype = SCIP_LINCONSTYPE_PRECEDENCE;
15465  SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15466  }
15467  else
15468  {
15469  constype = SCIP_LINCONSTYPE_VARBOUND;
15470  SCIPdebugMsg(scip, "classified as VARBOUND: ");
15471  }
15472  SCIPdebugPrintCons(scip, cons, NULL);
15473 
15474  SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15475 
15476  continue;
15477  }
15478 
15479  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15480  {
15481  SCIP_Real scale;
15482  SCIP_Real b;
15483  SCIP_Bool unmatched;
15484  int nnegbinvars;
15485 
15486  unmatched = FALSE;
15487  nnegbinvars = 0;
15488 
15489  scale = REALABS(consdata->vals[0]);
15490 
15491  /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15492  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15493  {
15494  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15495  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15496  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15497  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15498 
15499  if( consdata->vals[i] < 0.0 )
15500  nnegbinvars++;
15501  }
15502 
15503  if( !unmatched )
15504  {
15505  if( SCIPisEQ(scip, lhs, rhs) )
15506  {
15507  b = rhs/scale + nnegbinvars;
15508  if( SCIPisEQ(scip, 1.0, b) )
15509  {
15510  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15511  SCIPdebugPrintCons(scip, cons, NULL);
15513 
15514  continue;
15515  }
15516  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15517  {
15518  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15519  SCIPdebugPrintCons(scip, cons, NULL);
15521 
15522  continue;
15523  }
15524  }
15525 
15526  /* compute right hand side divided by scale */
15527  if( !SCIPisInfinity(scip, rhs) )
15528  b = rhs/scale + nnegbinvars;
15529  else
15530  b = SCIPinfinity(scip);
15531 
15532  if( SCIPisEQ(scip, 1.0, b) )
15533  {
15534  SCIPdebugMsg(scip, "classified as SETPACKING: ");
15535  SCIPdebugPrintCons(scip, cons, NULL);
15537 
15538  /* relax right hand side to prevent further classifications */
15539  rhs = SCIPinfinity(scip);
15540  }
15541  else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15542  {
15543  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15544  SCIPdebugPrintCons(scip, cons, NULL);
15545 
15547 
15548  /* relax right hand side to prevent further classifications */
15549  rhs = SCIPinfinity(scip);
15550  }
15551 
15552  if( !SCIPisInfinity(scip, lhs) )
15553  b = lhs/scale + nnegbinvars;
15554  else
15555  b = SCIPinfinity(scip);
15556 
15557  if( SCIPisEQ(scip, 1.0, b) )
15558  {
15559  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15560  SCIPdebugPrintCons(scip, cons, NULL);
15562 
15563  /* relax left hand side to prevent further classifications */
15564  lhs = -SCIPinfinity(scip);
15565  }
15566 
15567  /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15568  if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15569  continue;
15570  }
15571  }
15572 
15573  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15574  /* @todo If coefficients or rhs are not integral, we currently do not check
15575  * if the constraint could be scaled (finitely), such that they are.
15576  */
15577  {
15578  SCIP_Real b;
15579  SCIP_Bool unmatched;
15580 
15581  b = rhs;
15582  unmatched = FALSE;
15583  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15584  {
15585  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15586  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15587  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15588  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15589 
15590  if( SCIPisNegative(scip, consdata->vals[i]) )
15591  b -= consdata->vals[i];
15592  }
15593  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15594 
15595  if( !unmatched )
15596  {
15597  if( SCIPisEQ(scip, lhs, rhs) )
15598  {
15599  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15600  SCIPdebugPrintCons(scip, cons, NULL);
15601 
15603 
15604  continue;
15605  }
15606  else
15607  {
15608  SCIP_Bool matched;
15609 
15610  matched = FALSE;
15611  for( i = 0; i < consdata->nvars && !matched; i++ )
15612  {
15613  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15614  }
15615 
15616  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15617  SCIPdebugPrintCons(scip, cons, NULL);
15619  }
15620 
15621  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15622  if( SCIPisInfinity(scip, -lhs) )
15623  continue;
15624  else
15625  rhs = SCIPinfinity(scip);
15626  }
15627  }
15628 
15629  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15630  {
15631  SCIP_Real b;
15632  SCIP_Bool unmatched;
15633 
15634  unmatched = FALSE;
15635 
15636  b = rhs;
15637  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15638 
15639  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15640  {
15641  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15642  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15643  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15644  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15645  }
15646 
15647  if( !unmatched )
15648  {
15649  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15650  SCIPdebugPrintCons(scip, cons, NULL);
15652 
15653  /* check if finite left hand side allows for a second classification, relax already used right hand side */
15654  if( SCIPisInfinity(scip, -lhs) )
15655  continue;
15656  else
15657  rhs = SCIPinfinity(scip);
15658  }
15659  }
15660 
15661  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15662  {
15663  SCIP_Bool unmatched;
15664 
15665  unmatched = FALSE;
15666  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15667  {
15668  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15669  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15670  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15671  unmatched = TRUE;
15672  }
15673 
15674  if( !unmatched )
15675  {
15676  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15677  SCIPdebugPrintCons(scip, cons, NULL);
15678  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15679 
15680  continue;
15681  }
15682  }
15683 
15684  /* no special structure detected */
15685  SCIPdebugMsg(scip, "classified as GENERAL: ");
15686  SCIPdebugPrintCons(scip, cons, NULL);
15687  SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15688  }
15689 
15690  return SCIP_OKAY;
15691 }
15692 
15693 
15694 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15695 static
15696 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15697 { /*lint --e{715}*/
15698  int c;
15699 #ifdef SCIP_STATISTIC
15700  SCIP_CONSHDLRDATA* conshdlrdata;
15701  int ngoodconss;
15702  int nallconss;
15703 #endif
15704 
15705  /* delete all linear constraints that were upgraded to a more specific constraint type;
15706  * make sure, only active variables remain in the remaining constraints
15707  */
15708  assert(scip != NULL);
15709 
15710 #ifdef SCIP_STATISTIC
15711  /* count number of well behaved linear constraints */
15712  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15713  assert(conshdlrdata != NULL);
15714 
15715  ngoodconss = 0;
15716  nallconss = 0;
15717 
15718  for( c = 0; c < nconss; ++c )
15719  {
15720  SCIP_CONSDATA* consdata;
15721 
15722  if( SCIPconsIsDeleted(conss[c]) )
15723  continue;
15724 
15725  consdata = SCIPconsGetData(conss[c]);
15726  assert(consdata != NULL);
15727 
15728  if( consdata->upgraded )
15729  continue;
15730 
15731  nallconss++;
15732 
15733  consdataRecomputeMaxActivityDelta(scip, consdata);
15734 
15735  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15736  ngoodconss++;
15737  }
15738  if( nallconss )
15739  {
15740  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15741  }
15742 #endif
15743 
15744  for( c = 0; c < nconss; ++c )
15745  {
15746  SCIP_CONSDATA* consdata;
15747 
15748  if( SCIPconsIsDeleted(conss[c]) )
15749  continue;
15750 
15751  consdata = SCIPconsGetData(conss[c]);
15752  assert(consdata != NULL);
15753 
15754  if( consdata->upgraded )
15755  {
15756  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15757  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15758  */
15759  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15760  }
15761  else
15762  {
15763  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15764  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15765  }
15766  }
15767 
15768  return SCIP_OKAY;
15769 }
15770 
15771 /** solving process initialization method of constraint handler */
15772 static
15773 SCIP_DECL_CONSINITSOL(consInitsolLinear)
15774 { /*lint --e{715}*/
15775 
15776  /* add nlrow representation to NLP, if NLP had been constructed */
15777  if( SCIPisNLPConstructed(scip) )
15778  {
15779  int c;
15780  for( c = 0; c < nconss; ++c )
15781  {
15782  SCIP_CALL( addNlrow(scip, conss[c]) );
15783  }
15784  }
15785 
15786  return SCIP_OKAY;
15787 }
15788 
15789 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15790 static
15791 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15792 { /*lint --e{715}*/
15793  int c;
15794 
15795  assert(scip != NULL);
15796 
15797  /* release the rows and nlrows of all constraints */
15798  for( c = 0; c < nconss; ++c )
15799  {
15800  SCIP_CONSDATA* consdata;
15801 
15802  consdata = SCIPconsGetData(conss[c]);
15803  assert(consdata != NULL);
15804 
15805  if( consdata->row != NULL )
15806  {
15807  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15808  }
15809 
15810  if( consdata->nlrow != NULL )
15811  {
15812  SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
15813  }
15814  }
15815 
15816  /* if this is a restart, convert cutpool rows into linear constraints */
15817  if( restart )
15818  {
15819  int ncutsadded;
15820 
15821  ncutsadded = 0;
15822 
15823  /* create out of all active cuts in cutpool linear constraints */
15824  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15825 
15826  if( ncutsadded > 0 )
15827  {
15829  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15830  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15831  * line correctly
15832  */
15834  }
15835  }
15836 
15837  return SCIP_OKAY;
15838 }
15839 
15840 
15841 /** constraint activation notification method of constraint handler */
15842 static
15843 SCIP_DECL_CONSACTIVE(consActiveLinear)
15844 { /*lint --e{715}*/
15845  assert(cons != NULL);
15846 
15847  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
15848  {
15849  SCIP_CALL( addNlrow(scip, cons) );
15850  }
15851 
15852  return SCIP_OKAY;
15853 }
15854 
15855 /** constraint deactivation notification method of constraint handler */
15856 static
15857 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15858 { /*lint --e{715}*/
15859  SCIP_CONSDATA* consdata;
15860 
15861  assert(scip != NULL);
15862  assert(conshdlr != NULL);
15863  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15864  assert(cons != NULL );
15865 
15866  /* get constraint data */
15867  consdata = SCIPconsGetData(cons);
15868  assert(consdata != NULL);
15869 
15870  if( SCIPconsIsDeleted(cons) )
15871  {
15872  SCIP_CONSHDLRDATA* conshdlrdata;
15873 
15874  /* check for event handler */
15875  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15876  assert(conshdlrdata != NULL);
15877  assert(conshdlrdata->eventhdlr != NULL);
15878 
15879  /* free event data */
15880  if( consdata->eventdata != NULL )
15881  {
15882  /* drop bound change events of variables */
15883  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15884  }
15885  assert(consdata->eventdata == NULL);
15886  }
15887 
15888  /* remove row from NLP, if still in solving
15889  * if we are in exitsolve, the whole NLP will be freed anyway
15890  */
15891  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
15892  {
15893  SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
15894  }
15895 
15896  return SCIP_OKAY;
15897 }
15898 
15899 
15900 /** frees specific constraint data */
15901 static
15902 SCIP_DECL_CONSDELETE(consDeleteLinear)
15903 { /*lint --e{715}*/
15904  assert(scip != NULL);
15905  assert(conshdlr != NULL);
15906  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15907 
15908  if( (*consdata)->eventdata != NULL )
15909  {
15910  SCIP_CONSHDLRDATA* conshdlrdata;
15911 
15912  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15913  assert(conshdlrdata != NULL);
15914 
15915  /* drop all events */
15916  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15917  assert((*consdata)->eventdata == NULL);
15918  }
15919 
15920  /* free linear constraint */
15921  SCIP_CALL( consdataFree(scip, consdata) );
15922 
15923  return SCIP_OKAY;
15924 }
15925 
15926 
15927 /** transforms constraint data into data belonging to the transformed problem */
15928 static
15929 SCIP_DECL_CONSTRANS(consTransLinear)
15930 { /*lint --e{715}*/
15931  SCIP_CONSDATA* sourcedata;
15932  SCIP_CONSDATA* targetdata;
15933 
15934  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15935 
15936  assert(scip != NULL);
15937  assert(conshdlr != NULL);
15938  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15939  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15940  assert(sourcecons != NULL);
15941  assert(targetcons != NULL);
15942 
15943  sourcedata = SCIPconsGetData(sourcecons);
15944  assert(sourcedata != NULL);
15945  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15946 
15947  /* create linear constraint data for target constraint */
15948  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15949 
15950 #ifndef NDEBUG
15951  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15952  if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15953  {
15954  int n;
15955  for(n = targetdata->nvars - 1; n >= 0; --n )
15956  assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15957  }
15958 #endif
15959 
15960  /* create target constraint */
15961  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15962  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15963  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15964  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15965  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15966 
15967  return SCIP_OKAY;
15968 }
15969 
15970 
15971 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15972 static
15973 SCIP_DECL_CONSINITLP(consInitlpLinear)
15974 { /*lint --e{715}*/
15975  int c;
15976 
15977  assert(scip != NULL);
15978  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15979 
15980  *infeasible = FALSE;
15981 
15982  for( c = 0; c < nconss && !(*infeasible); ++c )
15983  {
15984  assert(SCIPconsIsInitial(conss[c]));
15985  SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15986  }
15987 
15988  return SCIP_OKAY;
15989 }
15990 
15991 
15992 /** separation method of constraint handler for LP solutions */
15993 static
15994 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15995 { /*lint --e{715}*/
15996  SCIP_CONSHDLRDATA* conshdlrdata;
15997  SCIP_Real loclowerbound;
15998  SCIP_Real glblowerbound;
15999  SCIP_Real cutoffbound;
16000  SCIP_Real maxbound;
16001  SCIP_Bool separatecards;
16002  SCIP_Bool cutoff;
16003  int c;
16004  int depth;
16005  int nrounds;
16006  int maxsepacuts;
16007  int ncuts;
16008 
16009  assert(scip != NULL);
16010  assert(conshdlr != NULL);
16011  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16012  assert(result != NULL);
16014  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16015  assert(conshdlrdata != NULL);
16016  depth = SCIPgetDepth(scip);
16017  nrounds = SCIPgetNSepaRounds(scip);
16018 
16019  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16020 
16021  *result = SCIP_DIDNOTRUN;
16022 
16023  /* only call the separator a given number of times at each node */
16024  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16025  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16026  return SCIP_OKAY;
16027 
16028  /* get the maximal number of cuts allowed in a separation round */
16029  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16030 
16031  /* check if we want to produce knapsack cardinality cuts at this node */
16032  loclowerbound = SCIPgetLocalLowerbound(scip);
16033  glblowerbound = SCIPgetLowerbound(scip);
16034  cutoffbound = SCIPgetCutoffbound(scip);
16035  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
16036  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
16037  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
16038 
16039  *result = SCIP_DIDNOTFIND;
16040  ncuts = 0;
16041  cutoff = FALSE;
16042 
16043  /* check all useful linear constraints for feasibility */
16044  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16045  {
16046  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16047  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
16048  }
16049 
16050  /* adjust return value */
16051  if( cutoff )
16052  *result = SCIP_CUTOFF;
16053  else if( ncuts > 0 )
16054  *result = SCIP_SEPARATED;
16055 
16056  /* combine linear constraints to get more cuts */
16057  /**@todo further cuts of linear constraints */
16058 
16059  return SCIP_OKAY;
16060 }
16061 
16062 
16063 /** separation method of constraint handler for arbitrary primal solutions */
16064 static
16065 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
16066 { /*lint --e{715}*/
16067  SCIP_CONSHDLRDATA* conshdlrdata;
16068  int c;
16069  int depth;
16070  int nrounds;
16071  int maxsepacuts;
16072  int ncuts;
16073  SCIP_Bool cutoff;
16074 
16075  assert(scip != NULL);
16076  assert(conshdlr != NULL);
16077  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16078  assert(result != NULL);
16079 
16080  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16081  assert(conshdlrdata != NULL);
16082  depth = SCIPgetDepth(scip);
16083  nrounds = SCIPgetNSepaRounds(scip);
16085  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
16086 
16087  *result = SCIP_DIDNOTRUN;
16088 
16089  /* only call the separator a given number of times at each node */
16090  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
16091  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
16092  return SCIP_OKAY;
16093 
16094  /* get the maximal number of cuts allowed in a separation round */
16095  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
16096 
16097  *result = SCIP_DIDNOTFIND;
16098  ncuts = 0;
16099  cutoff = FALSE;
16100 
16101  /* check all useful linear constraints for feasibility */
16102  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
16103  {
16104  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
16105  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
16106  }
16107 
16108  /* adjust return value */
16109  if( cutoff )
16110  *result = SCIP_CUTOFF;
16111  else if( ncuts > 0 )
16112  *result = SCIP_SEPARATED;
16113 
16114  /* combine linear constraints to get more cuts */
16115  /**@todo further cuts of linear constraints */
16116 
16117  return SCIP_OKAY;
16118 }
16119 
16120 
16121 /** constraint enforcing method of constraint handler for LP solutions */
16122 static
16123 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
16124 { /*lint --e{715}*/
16125  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
16126 
16127  return SCIP_OKAY;
16128 }
16129 
16130 /** constraint enforcing method of constraint handler for relaxation solutions */
16131 static
16132 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
16133 { /*lint --e{715}*/
16134  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
16135 
16136  return SCIP_OKAY;
16137 }
16138 
16139 /** constraint enforcing method of constraint handler for pseudo solutions */
16140 static
16141 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
16142 { /*lint --e{715}*/
16143  SCIP_CONSHDLRDATA* conshdlrdata;
16144  SCIP_Bool checkrelmaxabs;
16145  SCIP_Bool violated;
16146  int c;
16147 
16148  assert(scip != NULL);
16149  assert(conshdlr != NULL);
16150  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16151  assert(result != NULL);
16152 
16153  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16154  assert(conshdlrdata != NULL);
16155 
16156  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16157 
16158  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
16159 
16160  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16161  if( objinfeasible )
16162  {
16163  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16164 
16165  *result = SCIP_DIDNOTRUN;
16166  return SCIP_OKAY;
16167  }
16168 
16169  /* check all linear constraints for feasibility */
16170  violated = FALSE;
16171  for( c = 0; c < nconss && !violated; ++c )
16172  {
16173  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16174  }
16175 
16176  if( violated )
16177  *result = SCIP_INFEASIBLE;
16178  else
16179  *result = SCIP_FEASIBLE;
16180 
16181  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16182 
16183  return SCIP_OKAY;
16184 }
16185 
16186 
16187 /** feasibility check method of constraint handler for integral solutions */
16188 static
16189 SCIP_DECL_CONSCHECK(consCheckLinear)
16190 { /*lint --e{715}*/
16191  SCIP_CONSHDLRDATA* conshdlrdata;
16192  SCIP_Bool checkrelmaxabs;
16193  int c;
16194 
16195  assert(scip != NULL);
16196  assert(conshdlr != NULL);
16197  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16198  assert(result != NULL);
16199 
16200  *result = SCIP_FEASIBLE;
16201 
16202  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16203  assert(conshdlrdata != NULL);
16204 
16205  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16206 
16207  /*debugMsg(scip, "Check method of linear constraints\n");*/
16209  /* check all linear constraints for feasibility */
16210  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16211  {
16212  SCIP_Bool violated = FALSE;
16213  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16214 
16215  if( violated )
16216  {
16217  *result = SCIP_INFEASIBLE;
16218 
16219  if( printreason )
16220  {
16221  SCIP_CONSDATA* consdata;
16222  SCIP_Real activity;
16223 
16224  consdata = SCIPconsGetData(conss[c]);
16225  assert( consdata != NULL);
16226 
16227  activity = consdataGetActivity(scip, consdata, sol);
16228 
16229  SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16230  SCIPinfoMessage(scip, NULL, ";\n");
16231 
16232  if( activity == SCIP_INVALID ) /*lint !e777*/
16233  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16234  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16235  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16236  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16237  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16238  }
16239  }
16240  }
16241 
16242  return SCIP_OKAY;
16243 }
16244 
16245 
16246 /** domain propagation method of constraint handler */
16247 static
16248 SCIP_DECL_CONSPROP(consPropLinear)
16249 { /*lint --e{715}*/
16250  SCIP_CONSHDLRDATA* conshdlrdata;
16251  SCIP_Bool rangedrowpropagation = FALSE;
16252  SCIP_Bool tightenbounds;
16253  SCIP_Bool cutoff;
16254 
16255  int nchgbds;
16256  int i;
16257 
16258  assert(scip != NULL);
16259  assert(conshdlr != NULL);
16260  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16261  assert(result != NULL);
16262 
16263  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16264  assert(conshdlrdata != NULL);
16265 
16266  /*debugMsg(scip, "Prop method of linear constraints\n");*/
16268  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16269  if( SCIPinProbing(scip) )
16270  tightenbounds = TRUE;
16271  else
16272  {
16273  int depth;
16274  int propfreq;
16275  int tightenboundsfreq;
16276  int rangedrowfreq;
16277 
16278  depth = SCIPgetDepth(scip);
16279  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16280  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16281  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16282  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16283 
16284  /* check if we want to do ranged row propagation */
16285  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16286  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16287  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16288  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16289  rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16290  && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16291  }
16292 
16293  cutoff = FALSE;
16294  nchgbds = 0;
16295 
16296  /* process constraints marked for propagation */
16297  for( i = 0; i < nmarkedconss && !cutoff; i++ )
16298  {
16299  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16300  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16301  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16302  }
16303 
16304  /* adjust result code */
16305  if( cutoff )
16306  *result = SCIP_CUTOFF;
16307  else if( nchgbds > 0 )
16308  *result = SCIP_REDUCEDDOM;
16309  else
16310  *result = SCIP_DIDNOTFIND;
16311 
16312  return SCIP_OKAY;
16313 }
16314 
16315 
16316 #define MAXCONSPRESOLROUNDS 10
16317 /** presolving method of constraint handler */
16318 static
16319 SCIP_DECL_CONSPRESOL(consPresolLinear)
16320 { /*lint --e{715}*/
16321  SCIP_CONSHDLRDATA* conshdlrdata;
16322  SCIP_CONS* cons;
16323  SCIP_CONSDATA* consdata;
16324  SCIP_Real minactivity;
16325  SCIP_Real maxactivity;
16326  SCIP_Bool minactisrelax;
16327  SCIP_Bool maxactisrelax;
16328  SCIP_Bool isminsettoinfinity;
16329  SCIP_Bool ismaxsettoinfinity;
16330  SCIP_Bool cutoff;
16331  int oldnfixedvars;
16332  int oldnaggrvars;
16333  int oldnchgbds;
16334  int oldndelconss;
16335  int oldnupgdconss;
16336  int oldnchgcoefs;
16337  int oldnchgsides;
16338  int firstchange;
16339  int firstupgradetry;
16340  int c;
16341 
16342  assert(scip != NULL);
16343  assert(conshdlr != NULL);
16344  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16345  assert(result != NULL);
16346 
16347  /*debugMsg(scip, "Presol method of linear constraints\n");*/
16348 
16349  /* remember old preprocessing counters */
16350  cutoff = FALSE;
16351  oldnfixedvars = *nfixedvars;
16352  oldnaggrvars = *naggrvars;
16353  oldnchgbds = *nchgbds;
16354  oldndelconss = *ndelconss;
16355  oldnupgdconss = *nupgdconss;
16356  oldnchgcoefs = *nchgcoefs;
16357  oldnchgsides = *nchgsides;
16358 
16359  /* get constraint handler data */
16360  conshdlrdata = SCIPconshdlrGetData(conshdlr);
16361  assert(conshdlrdata != NULL);
16362 
16363  /* process single constraints */
16364  firstchange = INT_MAX;
16365  firstupgradetry = INT_MAX;
16366  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16367  {
16368  int npresolrounds;
16369  SCIP_Bool infeasible;
16370 
16371  infeasible = FALSE;
16372 
16373  cons = conss[c];
16374  assert(SCIPconsIsActive(cons));
16375  consdata = SCIPconsGetData(cons);
16376  assert(consdata != NULL);
16377 
16378  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16379  if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16380  {
16381  consdata->lhs = consdata->rhs;
16382  assert(consdata->row == NULL);
16383  }
16384 
16385  if( consdata->eventdata == NULL )
16386  {
16387  /* catch bound change events of variables */
16388  SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16389  assert(consdata->eventdata != NULL);
16390  }
16391 
16392  /* constraint should not be already presolved in the initial round */
16393  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16394  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16395  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16396  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16397 
16398  /* incorporate fixings and aggregations in constraint */
16399  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16400 
16401  if( infeasible )
16402  {
16403  SCIPdebugMsg(scip, " -> infeasible fixing\n");
16404  cutoff = TRUE;
16405  break;
16406  }
16407 
16408  assert(consdata->removedfixings);
16409 
16410  /* we can only presolve linear constraints, that are not modifiable */
16411  if( SCIPconsIsModifiable(cons) )
16412  continue;
16413 
16414  /* remember the first changed constraint to begin the next aggregation round with */
16415  if( firstchange == INT_MAX && consdata->changed )
16416  firstchange = c;
16417 
16418  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16419  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16420  firstupgradetry = c;
16421 
16422  /* check, if constraint is already preprocessed */
16423  if( consdata->presolved )
16424  continue;
16425 
16426  assert(SCIPconsIsActive(cons));
16427 
16428  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16429  SCIPdebugPrintCons(scip, cons, NULL);
16430 
16431  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16432  * to avoid nearly infinite cycling due to very small bound changes)
16433  */
16434  npresolrounds = 0;
16435  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16436  {
16437  assert(!cutoff);
16438  npresolrounds++;
16439 
16440  /* mark constraint being presolved and propagated */
16441  consdata->presolved = TRUE;
16442  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16443 
16444  /* normalize constraint */
16445  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16446 
16447  if( infeasible )
16448  {
16449  SCIPdebugMsg(scip, " -> infeasible normalization\n");
16450  cutoff = TRUE;
16451  break;
16452  }
16453 
16454  /* tighten left and right hand side due to integrality */
16455  SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16456 
16457  if( infeasible )
16458  {
16459  SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16460  cutoff = TRUE;
16461  break;
16462  }
16463 
16464  /* check bounds */
16465  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16466  {
16467  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16468  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16469  cutoff = TRUE;
16470  break;
16471  }
16472 
16473  /* tighten variable's bounds */
16474  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16475  if( cutoff )
16476  break;
16477 
16478  /* check for fixed variables */
16479  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16480  if( cutoff )
16481  break;
16482 
16483  /* check constraint for infeasibility and redundancy */
16484  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16485  &isminsettoinfinity, &ismaxsettoinfinity);
16486  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16487  {
16488  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16489  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16490  cutoff = TRUE;
16491  break;
16492  }
16493  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16494  {
16495  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16496  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16497  SCIP_CALL( SCIPdelCons(scip, cons) );
16498  assert(!SCIPconsIsActive(cons));
16499 
16500  if( !consdata->upgraded )
16501  (*ndelconss)++;
16502  break;
16503  }
16504  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) )
16505  {
16506  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16507  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16508  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16509  if( !consdata->upgraded )
16510  (*nchgsides)++;
16511  }
16512  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
16513  {
16514  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16515  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16516  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16517  if( !consdata->upgraded )
16518  (*nchgsides)++;
16519  }
16520 
16521  /* handle empty constraint */
16522  if( consdata->nvars == 0 )
16523  {
16524  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16525  {
16526  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16527  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16528  cutoff = TRUE;
16529  }
16530  else
16531  {
16532  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16533  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16534  SCIP_CALL( SCIPdelCons(scip, cons) );
16535  assert(!SCIPconsIsActive(cons));
16536 
16537  if( !consdata->upgraded )
16538  (*ndelconss)++;
16539  }
16540  break;
16541  }
16542 
16543  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16544  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16545 
16546  /* try to simplify inequalities */
16547  if( conshdlrdata->simplifyinequalities )
16548  {
16549  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16550 
16551  if( cutoff )
16552  break;
16553  }
16554 
16555  /* aggregation variable in equations */
16556  if( conshdlrdata->aggregatevariables )
16557  {
16558  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16559  if( cutoff )
16560  break;
16561  }
16562  }
16563 
16564  if( !cutoff && !SCIPisStopped(scip) )
16565  {
16566  /* perform ranged row propagation */
16567  if( conshdlrdata->rangedrowpropagation )
16568  {
16569  int lastnfixedvars;
16570 
16571  lastnfixedvars = *nfixedvars;
16572 
16573  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16574  if( !cutoff )
16575  {
16576  if( lastnfixedvars < *nfixedvars )
16577  {
16578  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16579  }
16580  }
16581  }
16582 
16583  /* extract cliques from constraint */
16584  if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16585  {
16586  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16587  nfixedvars, nchgbds, &cutoff) );
16588 
16589  /* check if the constraint got redundant or infeasible */
16590  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16591  {
16592  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16593  {
16594  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16595  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16596  cutoff = TRUE;
16597  }
16598  else
16599  {
16600  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16601  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16602  SCIP_CALL( SCIPdelCons(scip, cons) );
16603  assert(!SCIPconsIsActive(cons));
16604 
16605  if( !consdata->upgraded )
16606  (*ndelconss)++;
16607  }
16608  }
16609  }
16610 
16611  /* convert special equalities */
16612  if( !cutoff && SCIPconsIsActive(cons) )
16613  {
16614  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16615  }
16616 
16617  /* apply dual presolving for variables that appear in only one constraint */
16618  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16619  {
16620  SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16621  }
16622 
16623  /* check if an inequality is parallel to the objective function */
16624  if( !cutoff && SCIPconsIsActive(cons) )
16625  {
16626  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16627  }
16628 
16629  /* remember the first changed constraint to begin the next aggregation round with */
16630  if( firstchange == INT_MAX && consdata->changed )
16631  firstchange = c;
16632 
16633  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16634  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16635  firstupgradetry = c;
16636  }
16637 
16638  /* singleton column stuffing */
16639  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16640  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16641  {
16642  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16643  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16644 
16645  /* handle empty constraint */
16646  if( consdata->nvars == 0 )
16647  {
16648  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16649  {
16650  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16651  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16652  cutoff = TRUE;
16653  }
16654  else
16655  {
16656  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16657  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16658  SCIP_CALL( SCIPdelCons(scip, cons) );
16659  assert(!SCIPconsIsActive(cons));
16660 
16661  if( !consdata->upgraded )
16662  (*ndelconss)++;
16663  }
16664  break;
16665  }
16666  }
16667  }
16668 
16669  /* process pairs of constraints: check them for redundancy and try to aggregate them;
16670  * only apply this expensive procedure in exhaustive presolving timing
16671  */
16672  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16673  {
16674  assert(firstchange >= 0);
16675 
16676  if( firstchange < nconss && conshdlrdata->presolusehashing )
16677  {
16678  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16679  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16680  ndelconss, nchgsides) );
16681  }
16682 
16683  if( firstchange < nconss && conshdlrdata->presolpairwise )
16684  {
16685  SCIP_CONS** usefulconss;
16686  int nusefulconss;
16687  int firstchangenew;
16688  SCIP_Longint npaircomparisons;
16689 
16690  npaircomparisons = 0;
16691  oldndelconss = *ndelconss;
16692  oldnchgsides = *nchgsides;
16693  oldnchgcoefs = *nchgcoefs;
16694 
16695  /* allocate temporary memory */
16696  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16697 
16698  nusefulconss = 0;
16699  firstchangenew = -1;
16700  for( c = 0; c < nconss; ++c )
16701  {
16702  /* update firstchange */
16703  if( c == firstchange )
16704  firstchangenew = nusefulconss;
16705 
16706  /* ignore inactive and modifiable constraints */
16707  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16708  continue;
16709 
16710  usefulconss[nusefulconss] = conss[c];
16711  ++nusefulconss;
16712  }
16713  firstchange = firstchangenew;
16714  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16715 
16716  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16717  {
16718  /* constraint has become inactive or modifiable during pairwise presolving */
16719  if( usefulconss[c] == NULL )
16720  continue;
16721 
16722  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16723 
16724  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16725  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16726  &cutoff, ndelconss, nchgsides, nchgcoefs) );
16727 
16728  if( npaircomparisons > conshdlrdata->nmincomparisons )
16729  {
16730  assert(npaircomparisons > 0);
16731  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16732  break;
16733  oldndelconss = *ndelconss;
16734  oldnchgsides = *nchgsides;
16735  oldnchgcoefs = *nchgcoefs;
16736  npaircomparisons = 0;
16737  }
16738  }
16739  /* free temporary memory */
16740  SCIPfreeBufferArray(scip, &usefulconss);
16741  }
16742  }
16743 
16744  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16745  * in linear constraints and we therefore have full information about it
16746  */
16747  if( !cutoff && firstupgradetry < nconss
16748  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16749  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16750  )
16751  {
16752  if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16753  {
16754  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16755  }
16756  }
16757 
16758  /* try to upgrade constraints into a more specific constraint type;
16759  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16760  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16761  */
16762  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16763  {
16764  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16765  {
16766  cons = conss[c];
16767 
16768  /* don't upgrade modifiable constraints */
16769  if( SCIPconsIsModifiable(cons) )
16770  continue;
16771 
16772  consdata = SCIPconsGetData(cons);
16773  assert(consdata != NULL);
16774 
16775  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16776  if( consdata->upgradetried )
16777  continue;
16778  /* @todo force that upgrade will be performed later? */
16779  if( !consdata->presolved )
16780  continue;
16781 
16782  consdata->upgradetried = TRUE;
16783  if( SCIPconsIsActive(cons) )
16784  {
16785  SCIP_CONS* upgdcons;
16786 
16787  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16788  if( upgdcons != NULL )
16789  {
16790  /* add the upgraded constraint to the problem */
16791  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16792  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16793  (*nupgdconss)++;
16794 
16795  /* mark the linear constraint being upgraded and to be removed after presolving;
16796  * don't delete it directly, because it may help to preprocess other linear constraints
16797  */
16798  assert(!consdata->upgraded);
16799  consdata->upgraded = TRUE;
16800 
16801  /* delete upgraded inequalities immediately;
16802  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16803  */
16804  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16805  || !conshdlrdata->presolpairwise
16806  || (conshdlrdata->maxaggrnormscale == 0.0) )
16807  {
16808  SCIP_CALL( SCIPdelCons(scip, cons) );
16809  }
16810  }
16811  }
16812  }
16813  }
16814 
16815  /* return the correct result code */
16816  if( cutoff )
16817  *result = SCIP_CUTOFF;
16818  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16819  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16820  *result = SCIP_SUCCESS;
16821  else
16822  *result = SCIP_DIDNOTFIND;
16823 
16824  return SCIP_OKAY;
16825 }
16826 
16827 
16828 /** propagation conflict resolving method of constraint handler */
16829 static
16830 SCIP_DECL_CONSRESPROP(consRespropLinear)
16831 { /*lint --e{715}*/
16832  assert(scip != NULL);
16833  assert(cons != NULL);
16834  assert(result != NULL);
16835 
16836  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16837 
16838  return SCIP_OKAY;
16839 }
16840 
16841 
16842 /** variable rounding lock method of constraint handler */
16843 static
16844 SCIP_DECL_CONSLOCK(consLockLinear)
16845 { /*lint --e{715}*/
16846  SCIP_CONSDATA* consdata;
16847  SCIP_Bool haslhs;
16848  SCIP_Bool hasrhs;
16849  int i;
16850 
16851  assert(scip != NULL);
16852  assert(cons != NULL);
16853  consdata = SCIPconsGetData(cons);
16854  assert(consdata != NULL);
16855 
16856  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16857  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16858 
16859  /* update rounding locks of every single variable */
16860  for( i = 0; i < consdata->nvars; ++i )
16861  {
16862  if( SCIPisPositive(scip, consdata->vals[i]) )
16863  {
16864  if( haslhs )
16865  {
16866  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16867  }
16868  if( hasrhs )
16869  {
16870  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16871  }
16872  }
16873  else
16874  {
16875  if( haslhs )
16876  {
16877  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16878  }
16879  if( hasrhs )
16880  {
16881  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16882  }
16883  }
16884  }
16885 
16886  return SCIP_OKAY;
16887 }
16888 
16889 
16890 /** variable deletion method of constraint handler */
16891 static
16892 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16893 {
16894  assert(scip != NULL);
16895  assert(conshdlr != NULL);
16896  assert(conss != NULL || nconss == 0);
16897 
16898  if( nconss > 0 )
16899  {
16900  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16901  }
16902 
16903  return SCIP_OKAY;
16904 }
16905 
16906 /** constraint display method of constraint handler */
16907 static
16908 SCIP_DECL_CONSPRINT(consPrintLinear)
16909 { /*lint --e{715}*/
16910  assert(scip != NULL);
16911  assert(conshdlr != NULL);
16912  assert(cons != NULL);
16913 
16914  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16915 
16916  return SCIP_OKAY;
16917 }
16918 
16919 /** constraint copying method of constraint handler */
16920 static
16921 SCIP_DECL_CONSCOPY(consCopyLinear)
16922 { /*lint --e{715}*/
16923  SCIP_VAR** sourcevars;
16924  SCIP_Real* sourcecoefs;
16925  const char* consname;
16926  int nvars;
16928  assert(scip != NULL);
16929  assert(sourcescip != NULL);
16930  assert(sourcecons != NULL);
16931 
16932  /* get variables and coefficients of the source constraint */
16933  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16934  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16935  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16936 
16937  if( name != NULL )
16938  consname = name;
16939  else
16940  consname = SCIPconsGetName(sourcecons);
16941 
16942  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16943  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16944  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16945  assert(cons != NULL || *valid == FALSE);
16946 
16947  /* @todo should also the checkabsolute flag of the constraint be copied? */
16948 
16949  return SCIP_OKAY;
16950 }
16951 
16952 /** find operators '<=', '==', '>=', [free] in input string and return those places
16953  *
16954  * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16955  */
16956 static
16957 void findOperators(
16958  const char* str, /**< null terminated input string */
16959  char** firstoperator, /**< pointer to store the string starting at the first operator */
16960  char** secondoperator, /**< pointer to store the string starting at the second operator */
16961  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16962  )
16963 {
16964  char* curr;
16965 
16966  assert(str != NULL);
16967  assert(firstoperator != NULL);
16968  assert(secondoperator != NULL);
16969 
16970  *firstoperator = NULL;
16971  *secondoperator = NULL;
16972 
16973  curr = (char*)str;
16974  *success = TRUE;
16975 
16976  /* loop over the input string to find all operators */
16977  while( *curr && *success )
16978  {
16979  SCIP_Bool found = FALSE;
16980  int increment = 1;
16981 
16982  /* try if we found a possible operator */
16983  switch( *curr )
16984  {
16985  case '<':
16986  case '=':
16987  case '>':
16988 
16989  /* check if the two characters curr[0,1] form an operator together */
16990  if( curr[1] == '=' )
16991  {
16992  found = TRUE;
16993 
16994  /* update increment to continue after this operator */
16995  increment = 2;
16996  }
16997  break;
16998  case '[':
16999  if( strncmp(curr, "[free]", 6) == 0 )
17000  {
17001  found = TRUE;
17002 
17003  /* update increment to continue after this operator */
17004  increment = 6;
17005  }
17006  break;
17007  default:
17008  break;
17009  }
17010 
17011  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
17012  if( found )
17013  {
17014  if( *firstoperator == NULL )
17015  {
17016  *firstoperator = curr;
17017  }
17018  else
17019  {
17020  if( *secondoperator != NULL )
17021  {
17022  SCIPerrorMessage("Found more than two operators in line %s\n", str);
17023  *success = FALSE;
17024  }
17025  else if( strncmp(*firstoperator, "<=", 2) != 0 )
17026  {
17027  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
17028  *success = FALSE;
17029  }
17030  else if( strncmp(curr, "<=", 2) != 0 )
17031  {
17032  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
17033  *success = FALSE;
17034  }
17035 
17036  *secondoperator = curr;
17037  }
17038  }
17039 
17040  curr += increment;
17041  }
17042 
17043  /* check if we did find at least one operator */
17044  if( *success )
17045  {
17046  if( *firstoperator == NULL )
17047  {
17048  SCIPerrorMessage("Could not find any operator in line %s\n", str);
17049  *success = FALSE;
17050  }
17051  }
17052 }
17053 
17054 /** constraint parsing method of constraint handler */
17055 static
17056 SCIP_DECL_CONSPARSE(consParseLinear)
17057 { /*lint --e{715}*/
17058  SCIP_VAR** vars;
17059  SCIP_Real* coefs;
17060  int nvars;
17061  int coefssize;
17062  int requsize;
17063  SCIP_Real lhs;
17064  SCIP_Real rhs;
17065  char* endptr;
17066  char* firstop;
17067  char* secondop;
17068  SCIP_Bool operatorsuccess;
17069  char* lhsstrptr;
17070  char* rhsstrptr;
17071  char* varstrptr;
17072 
17073  assert(scip != NULL);
17074  assert(success != NULL);
17075  assert(str != NULL);
17076  assert(name != NULL);
17077  assert(cons != NULL);
17078 
17079  /* set left and right hand side to their default values */
17080  lhs = -SCIPinfinity(scip);
17081  rhs = SCIPinfinity(scip);
17082 
17083  (*success) = FALSE;
17084 
17085  /* return of string empty */
17086  if( !*str )
17087  return SCIP_OKAY;
17088 
17089  /* ignore whitespace */
17090  SCIP_CALL( SCIPskipSpace((char**)&str) );
17091 
17092  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
17093  * and the special word [free]
17094  */
17095  findOperators(str, &firstop, &secondop, &operatorsuccess);
17096 
17097  /* if the grammar is not valid for parsing a linear constraint, return */
17098  if( ! operatorsuccess )
17099  return SCIP_OKAY;
17100 
17101  varstrptr = (char *)str;
17102  lhsstrptr = rhsstrptr = NULL;
17103  assert(firstop != NULL);
17104 
17105  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
17106  switch( *firstop )
17107  {
17108  case '<':
17109  assert(firstop[1] == '=');
17110  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
17111  if( secondop != NULL )
17112  {
17113  assert(secondop[0] == '<' && secondop[1] == '=');
17114  lhsstrptr = (char *)str;
17115  varstrptr = firstop + 2;
17116  rhsstrptr = secondop + 2;
17117  }
17118  else
17119  {
17120  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
17121  lhsstrptr = NULL;
17122  varstrptr = (char *)str;
17123  rhsstrptr = firstop + 2;
17124  }
17125  break;
17126  case '>':
17127  assert(firstop[1] == '=');
17128  assert(secondop == NULL);
17129  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
17130  lhsstrptr = firstop + 2;
17131  break;
17132  case '=':
17133  assert(firstop[1] == '=');
17134  assert(secondop == NULL);
17135  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
17136  rhsstrptr = firstop + 2;
17137  lhsstrptr = firstop + 2;
17138  break;
17139  case '[':
17140  assert(strncmp(firstop, "[free]", 6) == 0);
17141  assert(secondop == NULL);
17142  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
17143  break;
17144  default:
17145  /* it should not be possible that a different character appears in that position */
17146  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
17147  return SCIP_READERROR;
17148  }
17149 
17150  /* parse left hand side, if necessary */
17151  if( lhsstrptr != NULL )
17152  {
17153  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
17154  {
17155  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
17156  return SCIP_OKAY;
17157  }
17158 
17159  /* in case of an equation, assign the left also to the right hand side */
17160  if( rhsstrptr == lhsstrptr )
17161  rhs = lhs;
17162  }
17163 
17164  /* parse right hand side, if different from left hand side */
17165  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17166  {
17167  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17168  {
17169  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17170  return SCIP_OKAY;
17171  }
17172  }
17173 
17174  /* initialize buffers for storing the variables and coefficients */
17175  coefssize = 100;
17176  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
17177  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17178 
17179  assert(varstrptr != NULL);
17180 
17181  /* parse linear sum to get variables and coefficients */
17182  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17183 
17184  if( *success && requsize > coefssize )
17185  {
17186  /* realloc buffers and try again */
17187  coefssize = requsize;
17188  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
17189  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17190 
17191  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17192  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17193  }
17194 
17195  if( !*success )
17196  {
17197  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17198  }
17199  else
17200  {
17201  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17202  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17203  }
17204 
17205  SCIPfreeBufferArray(scip, &coefs);
17206  SCIPfreeBufferArray(scip, &vars);
17207 
17208  return SCIP_OKAY;
17209 }
17210 
17211 
17212 /** constraint method of constraint handler which returns the variables (if possible) */
17213 static
17214 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17215 { /*lint --e{715}*/
17216  SCIP_CONSDATA* consdata;
17217 
17218  consdata = SCIPconsGetData(cons);
17219  assert(consdata != NULL);
17220 
17221  if( varssize < consdata->nvars )
17222  (*success) = FALSE;
17223  else
17224  {
17225  assert(vars != NULL);
17226 
17227  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17228  (*success) = TRUE;
17229  }
17230 
17231  return SCIP_OKAY;
17232 }
17234 /**! [Callback for the number of variables]*/
17235 /** constraint method of constraint handler which returns the number of variables (if possible) */
17236 static
17237 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17238 { /*lint --e{715}*/
17239  SCIP_CONSDATA* consdata;
17240 
17241  consdata = SCIPconsGetData(cons);
17242  assert(consdata != NULL);
17243 
17244  (*nvars) = consdata->nvars;
17245  (*success) = TRUE;
17246 
17247  return SCIP_OKAY;
17248 }
17249 /**! [Callback for the number of variables]*/
17250 
17251 /*
17252  * Callback methods of event handler
17253  */
17254 
17255 /** execution method of event handler */
17256 static
17257 SCIP_DECL_EVENTEXEC(eventExecLinear)
17258 { /*lint --e{715}*/
17259  SCIP_CONS* cons;
17260  SCIP_CONSDATA* consdata;
17261  SCIP_VAR* var;
17262  SCIP_EVENTTYPE eventtype;
17263 
17264  assert(scip != NULL);
17265  assert(eventhdlr != NULL);
17266  assert(eventdata != NULL);
17267  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17268  assert(event != NULL);
17269 
17270  cons = eventdata->cons;
17271  assert(cons != NULL);
17272  consdata = SCIPconsGetData(cons);
17273  assert(consdata != NULL);
17274 
17275  /* we can skip events droped for deleted constraints */
17276  if( SCIPconsIsDeleted(cons) )
17277  return SCIP_OKAY;
17278 
17279  eventtype = SCIPeventGetType(event);
17280  var = SCIPeventGetVar(event);
17281 
17282  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17283  {
17284  SCIP_Real oldbound;
17285  SCIP_Real newbound;
17286  SCIP_Real val;
17287  int varpos;
17288 
17289  varpos = eventdata->varpos;
17290  assert(0 <= varpos && varpos < consdata->nvars);
17291  oldbound = SCIPeventGetOldbound(event);
17292  newbound = SCIPeventGetNewbound(event);
17293  assert(var != NULL);
17294  assert(consdata->vars[varpos] == var);
17295  val = consdata->vals[varpos];
17296 
17297  /* we only need to update the activities if the constraint is active,
17298  * otherwise we mark them to be invalid
17299  */
17300  if( SCIPconsIsActive(cons) )
17301  {
17302  /* update the activity values */
17303  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17304  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17305  else
17306  {
17307  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17308  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17309  }
17310  }
17311  else
17312  consdataInvalidateActivities(consdata);
17313 
17314  consdata->presolved = FALSE;
17315  consdata->rangedrowpropagated = 0;
17316 
17317  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17318  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17319  {
17320  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17321 
17322  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17323  if( consdata->maxactdeltavar == var )
17324  {
17325  consdata->maxactdelta = SCIP_INVALID;
17326  consdata->maxactdeltavar = NULL;
17327  }
17328 
17329  /* check whether bound tightening might now be successful */
17330  if( consdata->boundstightened > 0)
17331  {
17332  switch( eventtype )
17333  {
17335  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17336  consdata->boundstightened = 0;
17337  break;
17339  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17340  consdata->boundstightened = 0;
17341  break;
17342  default:
17343  SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
17344  return SCIP_INVALIDDATA;
17345  }
17346  }
17347  }
17348  /* update maximal activity delta if a bound was relaxed */
17349  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17350  {
17351  SCIP_Real lb;
17352  SCIP_Real ub;
17353  SCIP_Real domain;
17354  SCIP_Real delta;
17355 
17356  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17357 
17358  lb = SCIPvarGetLbLocal(var);
17359  ub = SCIPvarGetUbLocal(var);
17360 
17361  domain = ub - lb;
17362  delta = REALABS(val) * domain;
17363 
17364  if( delta > consdata->maxactdelta )
17365  {
17366  consdata->maxactdelta = delta;
17367  consdata->maxactdeltavar = var;
17368  }
17369  }
17370  }
17371  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17372  {
17373  /* we want to remove the fixed variable */
17374  consdata->presolved = FALSE;
17375  consdata->removedfixings = FALSE;
17376  consdata->rangedrowpropagated = 0;
17377 
17378  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17379  if( consdata->maxactdeltavar == var )
17380  {
17381  consdata->maxactdelta = SCIP_INVALID;
17382  consdata->maxactdeltavar = NULL;
17383  }
17384  }
17385  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17386  {
17387  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17388  assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17389  assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17390  consdata->presolved = FALSE;
17391  }
17392  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17393  {
17394  SCIP_Real oldbound;
17395  SCIP_Real newbound;
17396  SCIP_Real val;
17397  int varpos;
17398 
17399  varpos = eventdata->varpos;
17400  assert(0 <= varpos && varpos < consdata->nvars);
17401  oldbound = SCIPeventGetOldbound(event);
17402  newbound = SCIPeventGetNewbound(event);
17403  assert(var != NULL);
17404  assert(consdata->vars[varpos] == var);
17405  val = consdata->vals[varpos];
17406 
17407  consdata->rangedrowpropagated = 0;
17408 
17409  /* update the activity values */
17410  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17411  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17412  else
17413  {
17414  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17415  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17416  }
17417 
17418  /* if the variable is binary but not fixed it had to become binary due to this global change */
17419  if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17420  {
17421  if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17422  consdata->indexsorted = FALSE;
17423  else
17424  consdata->coefsorted = FALSE;
17425  }
17426  }
17427  else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17428  {
17429  assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17430 
17431  /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17432  consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17433 
17434  /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17435  consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17436  }
17437  else
17438  {
17439  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17440  consdata->varsdeleted = TRUE;
17441  }
17442 
17443  return SCIP_OKAY;
17444 }
17445 
17446 
17447 /*
17448  * Callback methods of conflict handler
17449  */
17450 
17451 /** conflict processing method of conflict handler (called when conflict was found) */
17452 static
17453 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17454 { /*lint --e{715}*/
17455  SCIP_VAR** vars;
17456  SCIP_Real* vals;
17457  SCIP_Real lhs;
17458  int i;
17459 
17460  assert(scip != NULL);
17461  assert(conflicthdlr != NULL);
17462  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17463  assert(bdchginfos != NULL || nbdchginfos == 0);
17464  assert(result != NULL);
17465 
17466  /* don't process already resolved conflicts */
17467  if( resolved )
17468  {
17469  *result = SCIP_DIDNOTRUN;
17470  return SCIP_OKAY;
17471  }
17473  *result = SCIP_DIDNOTFIND;
17474 
17475  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17476  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17477  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17478  lhs = 1.0;
17479  for( i = 0; i < nbdchginfos; ++i )
17480  {
17481  assert(bdchginfos != NULL);
17482 
17483  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17484 
17485  /* we can only treat binary variables */
17486  /**@todo extend linear conflict constraints to some non-binary cases */
17487  if( !SCIPvarIsBinary(vars[i]) )
17488  break;
17489 
17490  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17491  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17492  vals[i] = 1.0;
17493  else
17494  {
17495  vals[i] = -1.0;
17496  lhs -= 1.0;
17497  }
17498  }
17499 
17500  if( i == nbdchginfos )
17501  {
17502  SCIP_CONS* cons;
17503  SCIP_CONS* upgdcons;
17504  char consname[SCIP_MAXSTRLEN];
17505 
17506  /* create a constraint out of the conflict set */
17507  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17508  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17509  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17510 
17511  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17512  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17513  if( upgdcons != NULL )
17514  {
17515  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17516  cons = upgdcons;
17517  }
17518 
17519  /* add conflict to SCIP */
17520  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17521 
17522  *result = SCIP_CONSADDED;
17523  }
17524 
17525  /* free temporary memory */
17526  SCIPfreeBufferArray(scip, &vals);
17527  SCIPfreeBufferArray(scip, &vars);
17528 
17529  return SCIP_OKAY;
17530 }
17531 
17532 
17533 /*
17534  * Nonlinear constraint upgrading
17535  */
17536 
17537 /** tries to upgrade a nonlinear constraint into a linear constraint */
17538 static
17539 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17540 {
17541  SCIP_CONSDATA* consdata;
17542  SCIP_EXPR* expr;
17543  SCIP_Real lhs;
17544  SCIP_Real rhs;
17545  int i;
17546 
17547  assert(nupgdconss != NULL);
17548  assert(upgdconss != NULL);
17549  assert(upgdconsssize > 0);
17550 
17551  expr = SCIPgetExprNonlinear(cons);
17552  assert(expr != NULL);
17553 
17554  /* not a linear constraint if the expression is not a sum
17555  * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear)
17556  */
17557  if( !SCIPisExprSum(scip, expr) )
17558  return SCIP_OKAY;
17559 
17560  /* if at least one child is not a variable, then not a linear constraint */
17561  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17562  if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) )
17563  return SCIP_OKAY;
17564 
17565  /* consider constant part of the sum expression */
17566  lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17567  rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr));
17568 
17569  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17570  0, NULL, NULL, lhs, rhs,
17574  SCIPconsIsStickingAtNode(cons)) );
17575  assert(upgdconss[0] != NULL);
17576 
17577  consdata = SCIPconsGetData(upgdconss[0]);
17578 
17579  /* add linear terms */
17580  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) );
17581  for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
17582  {
17583  SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) );
17584  }
17585 
17586  /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17587  consdata->checkabsolute = TRUE;
17588 
17589  *nupgdconss = 1;
17590 
17591  SCIPdebugMsg(scip, "created linear constraint:\n");
17592  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17593 
17594  return SCIP_OKAY;
17595 } /*lint !e715*/
17596 
17597 /*
17598  * constraint specific interface methods
17599  */
17600 
17601 /** creates the handler for linear constraints and includes it in SCIP */
17603  SCIP* scip /**< SCIP data structure */
17604  )
17605 {
17606  SCIP_CONSHDLRDATA* conshdlrdata;
17607  SCIP_CONSHDLR* conshdlr;
17608  SCIP_EVENTHDLR* eventhdlr;
17609  SCIP_CONFLICTHDLR* conflicthdlr;
17610 
17611  assert(scip != NULL);
17612 
17613  /* create event handler for bound change events */
17615  eventExecLinear, NULL) );
17616 
17617  /* create conflict handler for linear constraints */
17619  conflictExecLinear, NULL) );
17620 
17621  /* create constraint handler data */
17622  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17623 
17624  /* include constraint handler */
17627  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17628  conshdlrdata) );
17629 
17630  assert(conshdlr != NULL);
17631 
17632  /* set non-fundamental callbacks via specific setter functions */
17633  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17634  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) );
17635  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17636  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17637  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17638  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17639  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17640  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) );
17641  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17642  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17643  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17644  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17645  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17646  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17647  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17648  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17649  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17650  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17652  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17653  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17655  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17656  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17657 
17658  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17659  {
17660  /* include the linear constraint upgrade in the nonlinear constraint handler */
17662  }
17663 
17664  /* add linear constraint handler parameters */
17665  SCIP_CALL( SCIPaddIntParam(scip,
17666  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17667  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17668  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17669  SCIP_CALL( SCIPaddIntParam(scip,
17670  "constraints/" CONSHDLR_NAME "/maxrounds",
17671  "maximal number of separation rounds per node (-1: unlimited)",
17672  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17673  SCIP_CALL( SCIPaddIntParam(scip,
17674  "constraints/" CONSHDLR_NAME "/maxroundsroot",
17675  "maximal number of separation rounds per node in the root node (-1: unlimited)",
17676  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17677  SCIP_CALL( SCIPaddIntParam(scip,
17678  "constraints/" CONSHDLR_NAME "/maxsepacuts",
17679  "maximal number of cuts separated per separation round",
17680  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17681  SCIP_CALL( SCIPaddIntParam(scip,
17682  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17683  "maximal number of cuts separated per separation round in the root node",
17684  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17686  "constraints/" CONSHDLR_NAME "/presolpairwise",
17687  "should pairwise constraint comparison be performed in presolving?",
17688  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17690  "constraints/" CONSHDLR_NAME "/presolusehashing",
17691  "should hash table be used for detecting redundant constraints in advance",
17692  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17693  SCIP_CALL( SCIPaddIntParam(scip,
17694  "constraints/" CONSHDLR_NAME "/nmincomparisons",
17695  "number for minimal pairwise presolve comparisons",
17696  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17698  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17699  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17700  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17702  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17703  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17704  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17706  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17707  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17708  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17710  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17711  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17712  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17714  "constraints/" CONSHDLR_NAME "/separateall",
17715  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17716  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17718  "constraints/" CONSHDLR_NAME "/aggregatevariables",
17719  "should presolving search for aggregations in equations",
17720  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17722  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17723  "should presolving try to simplify inequalities",
17724  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17726  "constraints/" CONSHDLR_NAME "/dualpresolving",
17727  "should dual presolving steps be performed?",
17728  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17730  "constraints/" CONSHDLR_NAME "/singletonstuffing",
17731  "should stuffing of singleton continuous variables be performed?",
17732  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17734  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17735  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17736  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17738  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17739  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17741  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17742  "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)?",
17743  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17745  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17746  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17747  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17749  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17750  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17751  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17753  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17754  "should presolving try to detect subsets of constraints parallel to the objective function?",
17755  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17757  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17758  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17759  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17761  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17762  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17763  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17764  SCIP_CALL( SCIPaddIntParam(scip,
17765  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17766  "maximum depth to apply ranged row propagation",
17767  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17768  SCIP_CALL( SCIPaddIntParam(scip,
17769  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17770  "frequency for applying ranged row propagation",
17771  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17773  "constraints/" CONSHDLR_NAME "/multaggrremove",
17774  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17775  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17777  "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17778  "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17779  &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17781  "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17782  "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17783  &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17785  "constraints/" CONSHDLR_NAME "/extractcliques",
17786  "should Cliques be extracted?",
17787  &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17788 
17789  return SCIP_OKAY;
17790 }
17791 
17792 /** includes a linear constraint update method into the linear constraint handler */
17794  SCIP* scip, /**< SCIP data structure */
17795  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17796  int priority, /**< priority of upgrading method */
17797  const char* conshdlrname /**< name of the constraint handler */
17798  )
17799 {
17800  SCIP_CONSHDLR* conshdlr;
17801  SCIP_CONSHDLRDATA* conshdlrdata;
17802  SCIP_LINCONSUPGRADE* linconsupgrade;
17803  char paramname[SCIP_MAXSTRLEN];
17804  char paramdesc[SCIP_MAXSTRLEN];
17805 
17806  assert(scip != NULL);
17807  assert(linconsupgd != NULL);
17808  assert(conshdlrname != NULL );
17809 
17810  /* find the linear constraint handler */
17811  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17812  if( conshdlr == NULL )
17813  {
17814  SCIPerrorMessage("linear constraint handler not found\n");
17815  return SCIP_PLUGINNOTFOUND;
17816  }
17817 
17818  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17819  assert(conshdlrdata != NULL);
17820 
17821  /* check if linear constraint update method already exists in constraint handler data */
17822  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17823  {
17824  /* create a linear constraint upgrade data object */
17825  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17826 
17827  /* insert linear constraint update method into constraint handler data */
17828  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17829 
17830  /* adds parameter to turn on and off the upgrading step */
17831  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17832  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17834  paramname, paramdesc,
17835  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17836  }
17837 
17838  return SCIP_OKAY;
17839 }
17840 
17841 /** creates and captures a linear constraint
17842  *
17843  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17844  */
17846  SCIP* scip, /**< SCIP data structure */
17847  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17848  const char* name, /**< name of constraint */
17849  int nvars, /**< number of nonzeros in the constraint */
17850  SCIP_VAR** vars, /**< array with variables of constraint entries */
17851  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17852  SCIP_Real lhs, /**< left hand side of constraint */
17853  SCIP_Real rhs, /**< right hand side of constraint */
17854  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17855  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17856  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17857  * Usually set to TRUE. */
17858  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17859  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17860  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17861  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17862  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17863  * Usually set to TRUE. */
17864  SCIP_Bool local, /**< is constraint only valid locally?
17865  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17866  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17867  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17868  * adds coefficients to this constraint. */
17869  SCIP_Bool dynamic, /**< is constraint subject to aging?
17870  * Usually set to FALSE. Set to TRUE for own cuts which
17871  * are separated as constraints. */
17872  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17873  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17874  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17875  * if it may be moved to a more global node?
17876  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17877  )
17878 {
17879  SCIP_CONSHDLR* conshdlr;
17880  SCIP_CONSDATA* consdata;
17881 
17882  assert(scip != NULL);
17883  assert(cons != NULL);
17884 
17885  /* find the linear constraint handler */
17886  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17887  if( conshdlr == NULL )
17888  {
17889  SCIPerrorMessage("linear constraint handler not found\n");
17890  return SCIP_PLUGINNOTFOUND;
17891  }
17892 
17893  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17894  * constraint after presolving we have to ensure that it holds active variables
17895  */
17896  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17897  {
17898  SCIP_VAR** consvars;
17899  SCIP_Real* consvals;
17900  SCIP_Real constant = 0.0;
17901  int nconsvars;
17902  int requiredsize;
17903 
17904  nconsvars = nvars;
17905  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17906  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17907 
17908  /* get active variables for new constraint */
17909  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17910 
17911  /* if space was not enough we need to resize the buffers */
17912  if( requiredsize > nconsvars )
17913  {
17914  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17915  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17916 
17917  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17918  assert(requiredsize <= nconsvars);
17919  }
17920 
17921  /* adjust sides and check that we do not subtract infinity values */
17922  if( SCIPisInfinity(scip, REALABS(constant)) )
17923  {
17924  if( constant < 0.0 )
17925  {
17926  if( SCIPisInfinity(scip, lhs) )
17927  {
17928  SCIPfreeBufferArray(scip, &consvals);
17929  SCIPfreeBufferArray(scip, &consvars);
17930 
17931  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);
17932 
17933  SCIPABORT();
17934  return SCIP_INVALIDDATA; /*lint !e527*/
17935  }
17936  if( SCIPisInfinity(scip, rhs) )
17937  {
17938  SCIPfreeBufferArray(scip, &consvals);
17939  SCIPfreeBufferArray(scip, &consvars);
17940 
17941  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);
17942 
17943  SCIPABORT();
17944  return SCIP_INVALIDDATA; /*lint !e527*/
17945  }
17946 
17947  lhs = -SCIPinfinity(scip);
17948  rhs = -SCIPinfinity(scip);
17949  }
17950  else
17951  {
17952  if( SCIPisInfinity(scip, -lhs) )
17953  {
17954  SCIPfreeBufferArray(scip, &consvals);
17955  SCIPfreeBufferArray(scip, &consvars);
17956 
17957  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);
17958 
17959  SCIPABORT();
17960  return SCIP_INVALIDDATA; /*lint !e527*/
17961  }
17962  if( SCIPisInfinity(scip, -rhs) )
17963  {
17964  SCIPfreeBufferArray(scip, &consvals);
17965  SCIPfreeBufferArray(scip, &consvars);
17966 
17967  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);
17968 
17969  SCIPABORT();
17970  return SCIP_INVALIDDATA; /*lint !e527*/
17971  }
17972 
17973  lhs = SCIPinfinity(scip);
17974  rhs = SCIPinfinity(scip);
17975  }
17976  }
17977  else
17978  {
17979  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17980  lhs -= constant;
17981  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17982  rhs -= constant;
17983 
17984  if( SCIPisInfinity(scip, -lhs) )
17985  lhs = -SCIPinfinity(scip);
17986  else if( SCIPisInfinity(scip, lhs) )
17987  lhs = SCIPinfinity(scip);
17988 
17989  if( SCIPisInfinity(scip, rhs) )
17990  rhs = SCIPinfinity(scip);
17991  else if( SCIPisInfinity(scip, -rhs) )
17992  rhs = -SCIPinfinity(scip);
17993  }
17994 
17995  /* create constraint data */
17996  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17997  assert(consdata != NULL);
17998 
17999  SCIPfreeBufferArray(scip, &consvals);
18000  SCIPfreeBufferArray(scip, &consvars);
18001  }
18002  else
18003  {
18004  /* create constraint data */
18005  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
18006  assert(consdata != NULL);
18007  }
18008 
18009 #ifndef NDEBUG
18010  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18011  if( check || enforce )
18012  {
18013  int n;
18014  for(n = consdata->nvars - 1; n >= 0; --n )
18015  assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
18016  }
18017 #endif
18018 
18019  /* create constraint */
18020  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
18021  local, modifiable, dynamic, removable, stickingatnode) );
18022 
18023  return SCIP_OKAY;
18024 }
18025 
18026 /** creates and captures a linear constraint
18027  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
18028  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
18029  *
18030  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
18031  *
18032  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
18033  */
18035  SCIP* scip, /**< SCIP data structure */
18036  SCIP_CONS** cons, /**< pointer to hold the created constraint */
18037  const char* name, /**< name of constraint */
18038  int nvars, /**< number of nonzeros in the constraint */
18039  SCIP_VAR** vars, /**< array with variables of constraint entries */
18040  SCIP_Real* vals, /**< array with coefficients of constraint entries */
18041  SCIP_Real lhs, /**< left hand side of constraint */
18042  SCIP_Real rhs /**< right hand side of constraint */
18043  )
18044 {
18045  assert(scip != NULL);
18046 
18047  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
18048  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
18049 
18050  return SCIP_OKAY;
18051 }
18052 
18053 /** creates by copying and captures a linear constraint */
18055  SCIP* scip, /**< target SCIP data structure */
18056  SCIP_CONS** cons, /**< pointer to store the created target constraint */
18057  SCIP* sourcescip, /**< source SCIP data structure */
18058  const char* name, /**< name of constraint */
18059  int nvars, /**< number of variables in source variable array */
18060  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
18061  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
18062  SCIP_Real lhs, /**< left hand side of the linear constraint */
18063  SCIP_Real rhs, /**< right hand side of the linear constraint */
18064  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
18065  * variables of the target SCIP */
18066  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
18067  * target constraints */
18068  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
18069  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
18070  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
18071  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
18072  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
18073  SCIP_Bool local, /**< is constraint only valid locally? */
18074  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
18075  SCIP_Bool dynamic, /**< is constraint subject to aging? */
18076  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
18077  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
18078  * if it may be moved to a more global node? */
18079  SCIP_Bool global, /**< create a global or a local copy? */
18080  SCIP_Bool* valid /**< pointer to store if the copying was valid */
18081  )
18082 {
18083  SCIP_VAR** vars;
18084  SCIP_Real* coefs;
18085 
18086  SCIP_Real constant;
18087  int requiredsize;
18088  int v;
18089  SCIP_Bool success;
18090 
18091  if( SCIPisGT(scip, lhs, rhs) )
18092  {
18093  *valid = FALSE;
18094  return SCIP_OKAY;
18095  }
18096 
18097  (*valid) = TRUE;
18098 
18099  if( nvars == 0 )
18100  {
18101  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
18102  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18103  return SCIP_OKAY;
18104  }
18105 
18106  /* duplicate variable array */
18107  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
18108 
18109  /* duplicate coefficient array */
18110  if( sourcecoefs != NULL )
18111  {
18112  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
18113  }
18114  else
18115  {
18116  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18117  for( v = 0; v < nvars; ++v )
18118  coefs[v] = 1.0;
18119  }
18120 
18121  constant = 0.0;
18122 
18123  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18124  * the target SCIP
18125  */
18126  if( !SCIPvarIsOriginal(vars[0]) )
18127  {
18128  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18129 
18130  if( requiredsize > nvars )
18131  {
18132  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18133  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18134 
18135  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18136  assert(requiredsize <= nvars);
18137  }
18138  }
18139  else
18140  {
18141  for( v = 0; v < nvars; ++v )
18142  {
18143  assert(SCIPvarIsOriginal(vars[v]));
18144  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18145  assert(vars[v] != NULL);
18146  }
18147  }
18148 
18149  success = TRUE;
18150  /* map variables of the source constraint to variables of the target SCIP */
18151  for( v = 0; v < nvars && success; ++v )
18152  {
18153  SCIP_VAR* var;
18154  var = vars[v];
18155 
18156  /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18157  assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18158 
18159  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18160  assert(!(success) || vars[v] != NULL);
18161  }
18162 
18163  /* only create the target constraint, if all variables could be copied */
18164  if( success )
18165  {
18166  if( !SCIPisInfinity(scip, -lhs) )
18167  lhs -= constant;
18168 
18169  if( !SCIPisInfinity(scip, rhs) )
18170  rhs -= constant;
18171 
18172  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18173  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18174  }
18175  else
18176  *valid = FALSE;
18177 
18178  /* free buffer array */
18179  SCIPfreeBufferArray(scip, &coefs);
18180  SCIPfreeBufferArray(scip, &vars);
18181 
18182  return SCIP_OKAY;
18183 }
18184 
18185 /** adds coefficient to linear constraint (if it is not zero) */
18187  SCIP* scip, /**< SCIP data structure */
18188  SCIP_CONS* cons, /**< constraint data */
18189  SCIP_VAR* var, /**< variable of constraint entry */
18190  SCIP_Real val /**< coefficient of constraint entry */
18191  )
18192 {
18193  assert(scip != NULL);
18194  assert(cons != NULL);
18195  assert(var != NULL);
18196 
18197  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18198  {
18199  SCIPerrorMessage("constraint is not linear\n");
18200  return SCIP_INVALIDDATA;
18201  }
18202 
18203  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18204  * constraint after presolving we have to ensure that it holds active variables
18205  */
18206  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18207  {
18208  SCIP_CONSDATA* consdata;
18209  SCIP_VAR** consvars;
18210  SCIP_Real* consvals;
18211  SCIP_Real constant = 0.0;
18212  SCIP_Real rhs;
18213  SCIP_Real lhs;
18214  int nconsvars;
18215  int requiredsize;
18216  int v;
18217 
18218  nconsvars = 1;
18219  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18220  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18221  consvars[0] = var;
18222  consvals[0] = val;
18223 
18224  /* get active variables for new constraint */
18225  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18226 
18227  /* if space was not enough we need to resize the buffers */
18228  if( requiredsize > nconsvars )
18229  {
18230  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18231  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18232 
18233  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18234  assert(requiredsize <= nconsvars);
18235  }
18236 
18237  consdata = SCIPconsGetData(cons);
18238  assert(consdata != NULL);
18239 
18240  lhs = consdata->lhs;
18241  rhs = consdata->rhs;
18242 
18243  /* adjust sides and check that we do not subtract infinity values */
18244  /* constant is infinite */
18245  if( SCIPisInfinity(scip, REALABS(constant)) )
18246  {
18247  if( constant < 0.0 )
18248  {
18249  if( SCIPisInfinity(scip, lhs) )
18250  {
18251  SCIPfreeBufferArray(scip, &consvals);
18252  SCIPfreeBufferArray(scip, &consvars);
18253 
18254  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));
18255 
18256  SCIPABORT();
18257  return SCIP_INVALIDDATA; /*lint !e527*/
18258  }
18259  if( SCIPisInfinity(scip, rhs) )
18260  {
18261  SCIPfreeBufferArray(scip, &consvals);
18262  SCIPfreeBufferArray(scip, &consvars);
18263 
18264  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));
18265 
18266  SCIPABORT();
18267  return SCIP_INVALIDDATA; /*lint !e527*/
18268  }
18269 
18270  lhs = -SCIPinfinity(scip);
18271  rhs = -SCIPinfinity(scip);
18272  }
18273  else
18274  {
18275  if( SCIPisInfinity(scip, -lhs) )
18276  {
18277  SCIPfreeBufferArray(scip, &consvals);
18278  SCIPfreeBufferArray(scip, &consvars);
18279 
18280  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));
18281 
18282  SCIPABORT();
18283  return SCIP_INVALIDDATA; /*lint !e527*/
18284  }
18285  if( SCIPisInfinity(scip, -rhs) )
18286  {
18287  SCIPfreeBufferArray(scip, &consvals);
18288  SCIPfreeBufferArray(scip, &consvars);
18289 
18290  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));
18291 
18292  SCIPABORT();
18293  return SCIP_INVALIDDATA; /*lint !e527*/
18294  }
18295 
18296  lhs = SCIPinfinity(scip);
18297  rhs = SCIPinfinity(scip);
18298  }
18299  }
18300  /* constant is not infinite */
18301  else
18302  {
18303  if( !SCIPisInfinity(scip, REALABS(lhs)) )
18304  lhs -= constant;
18305  if( !SCIPisInfinity(scip, REALABS(rhs)) )
18306  rhs -= constant;
18307 
18308  if( SCIPisInfinity(scip, -lhs) )
18309  lhs = -SCIPinfinity(scip);
18310  else if( SCIPisInfinity(scip, lhs) )
18311  lhs = SCIPinfinity(scip);
18312 
18313  if( SCIPisInfinity(scip, rhs) )
18314  rhs = SCIPinfinity(scip);
18315  else if( SCIPisInfinity(scip, -rhs) )
18316  rhs = -SCIPinfinity(scip);
18317  }
18318 
18319  /* add all active variables to constraint */
18320  for( v = nconsvars - 1; v >= 0; --v )
18321  {
18322  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18323  }
18324 
18325  /* update left and right hand sides */
18326  SCIP_CALL( chgLhs(scip, cons, lhs));
18327  SCIP_CALL( chgRhs(scip, cons, rhs));
18328 
18329  SCIPfreeBufferArray(scip, &consvals);
18330  SCIPfreeBufferArray(scip, &consvars);
18331  }
18332  else
18333  {
18334  SCIP_CALL( addCoef(scip, cons, var, val) );
18335  }
18336 
18337  return SCIP_OKAY;
18338 }
18339 
18340 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18341  * not yet contained in the constraint
18342  *
18343  * @note This method may only be called during problem creation stage for an original constraint and variable.
18344  *
18345  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18346  */
18348  SCIP* scip, /**< SCIP data structure */
18349  SCIP_CONS* cons, /**< constraint data */
18350  SCIP_VAR* var, /**< variable of constraint entry */
18351  SCIP_Real val /**< new coefficient of constraint entry */
18352  )
18353 {
18354  SCIP_CONSDATA* consdata;
18355  SCIP_VAR** vars;
18356  SCIP_Bool found;
18357  int i;
18358 
18359  assert(scip != NULL);
18360  assert(cons != NULL);
18361  assert(var != NULL);
18362 
18363  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18364  {
18365  SCIPerrorMessage("constraint is not linear\n");
18367  }
18368 
18369  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18370  {
18371  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18372  return SCIP_INVALIDDATA;
18373  }
18374 
18375  consdata = SCIPconsGetData(cons);
18376  assert(consdata != NULL);
18377 
18378  vars = consdata->vars;
18379  found = FALSE;
18380  i = 0;
18381  while( i < consdata->nvars )
18382  {
18383  if( vars[i] == var )
18384  {
18385  if( found || SCIPisZero(scip, val) )
18386  {
18387  SCIP_CALL( delCoefPos(scip, cons, i) );
18388 
18389  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18390  i--;
18391  }
18392  else
18393  {
18394  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18395  }
18396  found = TRUE;
18397  }
18398  i++;
18399  }
18400 
18401  if( !found && !SCIPisZero(scip, val) )
18402  {
18403  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18404  }
18405 
18406  return SCIP_OKAY;
18407 }
18408 
18409 /** deletes variable from linear constraint
18410  *
18411  * @note This method may only be called during problem creation stage for an original constraint and variable.
18412  *
18413  * @note This method requires linear time to search for occurences of the variable in the constraint data.
18414  */
18416  SCIP* scip, /**< SCIP data structure */
18417  SCIP_CONS* cons, /**< constraint data */
18418  SCIP_VAR* var /**< variable of constraint entry */
18419  )
18420 {
18421  assert(scip != NULL);
18422  assert(cons != NULL);
18423  assert(var != NULL);
18424 
18425  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18426 
18427  return SCIP_OKAY;
18428 }
18429 
18430 /** gets left hand side of linear constraint */
18432  SCIP* scip, /**< SCIP data structure */
18433  SCIP_CONS* cons /**< constraint data */
18434  )
18435 {
18436  SCIP_CONSDATA* consdata;
18437 
18438  assert(scip != NULL);
18439  assert(cons != NULL);
18440 
18441  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18442  {
18443  SCIPerrorMessage("constraint is not linear\n");
18444  SCIPABORT();
18445  return SCIP_INVALID; /*lint !e527*/
18446  }
18447 
18448  consdata = SCIPconsGetData(cons);
18449  assert(consdata != NULL);
18451  return consdata->lhs;
18452 }
18453 
18454 /** gets right hand side of linear constraint */
18456  SCIP* scip, /**< SCIP data structure */
18457  SCIP_CONS* cons /**< constraint data */
18458  )
18459 {
18460  SCIP_CONSDATA* consdata;
18461 
18462  assert(scip != NULL);
18463  assert(cons != NULL);
18464 
18465  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18466  {
18467  SCIPerrorMessage("constraint is not linear\n");
18468  SCIPABORT();
18469  return SCIP_INVALID; /*lint !e527*/
18470  }
18471 
18472  consdata = SCIPconsGetData(cons);
18473  assert(consdata != NULL);
18475  return consdata->rhs;
18476 }
18477 
18478 /** changes left hand side of linear constraint */
18480  SCIP* scip, /**< SCIP data structure */
18481  SCIP_CONS* cons, /**< constraint data */
18482  SCIP_Real lhs /**< new left hand side */
18483  )
18484 {
18485  assert(scip != NULL);
18486  assert(cons != NULL);
18487 
18488  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18489  {
18490  SCIPerrorMessage("constraint is not linear\n");
18491  return SCIP_INVALIDDATA;
18492  }
18493 
18494  SCIP_CALL( chgLhs(scip, cons, lhs) );
18495 
18496  return SCIP_OKAY;
18497 }
18499 /** changes right hand side of linear constraint */
18501  SCIP* scip, /**< SCIP data structure */
18502  SCIP_CONS* cons, /**< constraint data */
18503  SCIP_Real rhs /**< new right hand side */
18504  )
18505 {
18506  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18507  {
18508  SCIPerrorMessage("constraint is not linear\n");
18509  return SCIP_INVALIDDATA;
18510  }
18511 
18512  SCIP_CALL( chgRhs(scip, cons, rhs) );
18513 
18514  return SCIP_OKAY;
18515 }
18516 
18517 /** gets the number of variables in the linear constraint */
18518 int SCIPgetNVarsLinear(
18519  SCIP* scip, /**< SCIP data structure */
18520  SCIP_CONS* cons /**< constraint data */
18521  )
18522 {
18523  SCIP_CONSDATA* consdata;
18524 
18525  assert(scip != NULL);
18526  assert(cons != NULL);
18527 
18528  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18529  {
18530  SCIPerrorMessage("constraint is not linear\n");
18531  SCIPABORT();
18532  return -1; /*lint !e527*/
18533  }
18534 
18535  consdata = SCIPconsGetData(cons);
18536  assert(consdata != NULL);
18538  return consdata->nvars;
18539 }
18540 
18541 /** gets the array of variables in the linear constraint; the user must not modify this array! */
18543  SCIP* scip, /**< SCIP data structure */
18544  SCIP_CONS* cons /**< constraint data */
18545  )
18546 {
18547  SCIP_CONSDATA* consdata;
18548 
18549  assert(scip != NULL);
18550  assert(cons != NULL);
18551 
18552  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18553  {
18554  SCIPerrorMessage("constraint is not linear\n");
18555  SCIPABORT();
18556  return NULL; /*lint !e527*/
18557  }
18558 
18559  consdata = SCIPconsGetData(cons);
18560  assert(consdata != NULL);
18562  return consdata->vars;
18563 }
18564 
18565 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
18567  SCIP* scip, /**< SCIP data structure */
18568  SCIP_CONS* cons /**< constraint data */
18569  )
18570 {
18571  SCIP_CONSDATA* consdata;
18572 
18573  assert(scip != NULL);
18574  assert(cons != NULL);
18575 
18576  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18577  {
18578  SCIPerrorMessage("constraint is not linear\n");
18579  SCIPABORT();
18580  return NULL; /*lint !e527*/
18581  }
18582 
18583  consdata = SCIPconsGetData(cons);
18584  assert(consdata != NULL);
18586  return consdata->vals;
18587 }
18588 
18589 /** gets the activity of the linear constraint in the given solution
18590  *
18591  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18592  * comprises positive and negative infinity contributions
18593  */
18595  SCIP* scip, /**< SCIP data structure */
18596  SCIP_CONS* cons, /**< constraint data */
18597  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18598  )
18599 {
18600  SCIP_CONSDATA* consdata;
18601 
18602  assert(scip != NULL);
18603  assert(cons != NULL);
18604 
18605  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18606  {
18607  SCIPerrorMessage("constraint is not linear\n");
18608  SCIPABORT();
18609  return SCIP_INVALID; /*lint !e527*/
18610  }
18611 
18612  consdata = SCIPconsGetData(cons);
18613  assert(consdata != NULL);
18614 
18615  if( consdata->row != NULL )
18616  return SCIPgetRowSolActivity(scip, consdata->row, sol);
18617  else
18618  return consdataGetActivity(scip, consdata, sol);
18619 }
18620 
18621 /** gets the feasibility of the linear constraint in the given solution */
18623  SCIP* scip, /**< SCIP data structure */
18624  SCIP_CONS* cons, /**< constraint data */
18625  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
18626  )
18627 {
18628  SCIP_CONSDATA* consdata;
18629 
18630  assert(scip != NULL);
18631  assert(cons != NULL);
18632 
18633  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18634  {
18635  SCIPerrorMessage("constraint is not linear\n");
18636  SCIPABORT();
18637  return SCIP_INVALID; /*lint !e527*/
18638  }
18639 
18640  consdata = SCIPconsGetData(cons);
18641  assert(consdata != NULL);
18642 
18643  if( consdata->row != NULL )
18644  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18645  else
18646  return consdataGetFeasibility(scip, consdata, sol);
18647 }
18648 
18649 /** gets the dual solution of the linear constraint in the current LP */
18651  SCIP* scip, /**< SCIP data structure */
18652  SCIP_CONS* cons /**< constraint data */
18653  )
18654 {
18655  SCIP_CONSDATA* consdata;
18656 
18657  assert(scip != NULL);
18658  assert(cons != NULL);
18659  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18660 
18661  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18662  {
18663  SCIPerrorMessage("constraint is not linear\n");
18664  SCIPABORT();
18665  return SCIP_INVALID; /*lint !e527*/
18666  }
18667 
18668  consdata = SCIPconsGetData(cons);
18669  assert(consdata != NULL);
18670 
18671  if( consdata->row != NULL )
18672  return SCIProwGetDualsol(consdata->row);
18673  else
18674  return 0.0;
18675 }
18676 
18677 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
18679  SCIP* scip, /**< SCIP data structure */
18680  SCIP_CONS* cons /**< constraint data */
18681  )
18682 {
18683  SCIP_CONSDATA* consdata;
18684 
18685  assert(scip != NULL);
18686  assert(cons != NULL);
18687  assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18688 
18689  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18690  {
18691  SCIPerrorMessage("constraint is not linear\n");
18692  SCIPABORT();
18693  return SCIP_INVALID; /*lint !e527*/
18694  }
18695 
18696  consdata = SCIPconsGetData(cons);
18697  assert(consdata != NULL);
18698 
18699  if( consdata->row != NULL )
18700  return SCIProwGetDualfarkas(consdata->row);
18701  else
18702  return 0.0;
18703 }
18704 
18705 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18706  * the user must not modify the row!
18707  */
18709  SCIP* scip, /**< SCIP data structure */
18710  SCIP_CONS* cons /**< constraint data */
18711  )
18712 {
18713  SCIP_CONSDATA* consdata;
18714 
18715  assert(scip != NULL);
18716  assert(cons != NULL);
18717 
18718  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18719  {
18720  SCIPerrorMessage("constraint is not linear\n");
18721  SCIPABORT();
18722  return NULL; /*lint !e527*/
18723  }
18724 
18725  consdata = SCIPconsGetData(cons);
18726  assert(consdata != NULL);
18728  return consdata->row;
18729 }
18730 
18731 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
18733  SCIP* scip, /**< SCIP data structure */
18734  SCIP_CONS* cons, /**< source constraint to try to convert */
18735  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
18736  )
18737 {
18738  SCIP_CONSHDLR* conshdlr;
18739  SCIP_CONSHDLRDATA* conshdlrdata;
18740  SCIP_CONSDATA* consdata;
18741  SCIP_VAR* var;
18742  SCIP_Real val;
18743  SCIP_Real lb;
18744  SCIP_Real ub;
18745  SCIP_Real poscoeffsum;
18746  SCIP_Real negcoeffsum;
18747  SCIP_Bool infeasible;
18748  SCIP_Bool integral;
18749  int nchgsides = 0;
18750  int nposbin;
18751  int nnegbin;
18752  int nposint;
18753  int nnegint;
18754  int nposimpl;
18755  int nnegimpl;
18756  int nposimplbin;
18757  int nnegimplbin;
18758  int nposcont;
18759  int nnegcont;
18760  int ncoeffspone;
18761  int ncoeffsnone;
18762  int ncoeffspint;
18763  int ncoeffsnint;
18764  int ncoeffspfrac;
18765  int ncoeffsnfrac;
18766  int i;
18767 
18768  assert(scip != NULL);
18769  assert(cons != NULL);
18770  assert(upgdcons != NULL);
18771 
18772  *upgdcons = NULL;
18773 
18774  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18775  if( SCIPconsIsModifiable(cons) )
18776  return SCIP_OKAY;
18777 
18778  /* check for upgradability */
18779  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18780  return SCIP_OKAY;
18781 
18782  /* get the constraint handler and check, if it's really a linear constraint */
18783  conshdlr = SCIPconsGetHdlr(cons);
18784  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18785  {
18786  SCIPerrorMessage("constraint is not linear\n");
18787  return SCIP_INVALIDDATA;
18788  }
18789 
18790  /* get constraint handler data and constraint data */
18791  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18792  assert(conshdlrdata != NULL);
18793  consdata = SCIPconsGetData(cons);
18794  assert(consdata != NULL);
18795 
18796  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18797  if( consdata->upgraded )
18798  return SCIP_OKAY;
18799 
18800  /* check, if the constraint is already stored as LP row */
18801  if( consdata->row != NULL )
18802  {
18803  if( SCIProwIsInLP(consdata->row) )
18804  {
18805  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18806  return SCIP_INVALIDDATA;
18807  }
18808  else
18809  {
18810  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18811  }
18812  }
18813 
18814  /* normalize constraint */
18815  SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18816 
18817  /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18818  * skipped and we hope that the infeasibility gets detected later again.
18819  *
18820  * TODO: do we want to try to upgrade the constraint anyway?
18821  *
18822  * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18823  * proven to be infeasible.
18824  */
18825  if( infeasible ) /*lint !e774*/
18826  return SCIP_OKAY;
18827 
18828  /* tighten sides */
18829  SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18830 
18831  if( infeasible ) /*lint !e774*/
18832  return SCIP_OKAY;
18833 
18834  /*
18835  * calculate some statistics on linear constraint
18836  */
18837 
18838  nposbin = 0;
18839  nnegbin = 0;
18840  nposint = 0;
18841  nnegint = 0;
18842  nposimpl = 0;
18843  nnegimpl = 0;
18844  nposimplbin = 0;
18845  nnegimplbin = 0;
18846  nposcont = 0;
18847  nnegcont = 0;
18848  ncoeffspone = 0;
18849  ncoeffsnone = 0;
18850  ncoeffspint = 0;
18851  ncoeffsnint = 0;
18852  ncoeffspfrac = 0;
18853  ncoeffsnfrac = 0;
18854  integral = TRUE;
18855  poscoeffsum = 0.0;
18856  negcoeffsum = 0.0;
18857 
18858  for( i = 0; i < consdata->nvars; ++i )
18859  {
18860  var = consdata->vars[i];
18861  val = consdata->vals[i];
18862  lb = SCIPvarGetLbLocal(var);
18863  ub = SCIPvarGetUbLocal(var);
18864  assert(!SCIPisZero(scip, val));
18865 
18866  switch( SCIPvarGetType(var) )
18867  {
18868  case SCIP_VARTYPE_BINARY:
18869  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18870  integral = integral && SCIPisIntegral(scip, val);
18871  if( val >= 0.0 )
18872  nposbin++;
18873  else
18874  nnegbin++;
18875  break;
18876  case SCIP_VARTYPE_INTEGER:
18877  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18878  integral = integral && SCIPisIntegral(scip, val);
18879  if( val >= 0.0 )
18880  nposint++;
18881  else
18882  nnegint++;
18883  break;
18884  case SCIP_VARTYPE_IMPLINT:
18885  if( SCIPvarIsBinary(var) )
18886  {
18887  if( val >= 0.0 )
18888  nposimplbin++;
18889  else
18890  nnegimplbin++;
18891  }
18892  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18893  integral = integral && SCIPisIntegral(scip, val);
18894  if( val >= 0.0 )
18895  nposimpl++;
18896  else
18897  nnegimpl++;
18898  break;
18900  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18901  if( val >= 0.0 )
18902  nposcont++;
18903  else
18904  nnegcont++;
18905  break;
18906  default:
18907  SCIPerrorMessage("unknown variable type\n");
18908  return SCIP_INVALIDDATA;
18909  }
18910  if( SCIPisEQ(scip, val, 1.0) )
18911  ncoeffspone++;
18912  else if( SCIPisEQ(scip, val, -1.0) )
18913  ncoeffsnone++;
18914  else if( SCIPisIntegral(scip, val) )
18915  {
18916  if( SCIPisPositive(scip, val) )
18917  ncoeffspint++;
18918  else
18919  ncoeffsnint++;
18920  }
18921  else
18922  {
18923  if( SCIPisPositive(scip, val) )
18924  ncoeffspfrac++;
18925  else
18926  ncoeffsnfrac++;
18927  }
18928  if( SCIPisPositive(scip, val) )
18929  poscoeffsum += val;
18930  else
18931  negcoeffsum += val;
18932  }
18933 
18934  /*
18935  * call the upgrading methods
18936  */
18937 
18938  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18939  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18940  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",
18941  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18942  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18943  poscoeffsum, negcoeffsum, integral);
18944 
18945  /* try all upgrading methods in priority order in case the upgrading step is enable */
18946  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18947  {
18948  if( conshdlrdata->linconsupgrades[i]->active )
18949  {
18950  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18951  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18952  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18953  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18954  poscoeffsum, negcoeffsum, integral,
18955  upgdcons) );
18956  }
18957  }
18958 
18959 #ifdef SCIP_DEBUG
18960  if( *upgdcons != NULL )
18961  {
18962  SCIPdebugPrintCons(scip, cons, NULL);
18963  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18964  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18965  }
18966 #endif
18967 
18968  return SCIP_OKAY; /*lint !e438*/
18969 }
18970 
18971 /** cleans up (multi-)aggregations and fixings from linear constraints */
18973  SCIP* scip, /**< SCIP data structure */
18974  SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
18975  SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */
18976  )
18977 {
18978  SCIP_CONSHDLR* conshdlr;
18979  SCIP_CONS** conss;
18980  int nconss;
18981  int i;
18982 
18983  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18984  if( conshdlr == NULL )
18985  return SCIP_OKAY;
18986 
18987  assert(infeasible != NULL);
18988  *infeasible = FALSE;
18989 
18990  nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18991  conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18992 
18993  for( i = 0; i < nconss; ++i )
18994  {
18995  SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18996 
18997  if( *infeasible )
18998  break;
18999  }
19000 
19001  return SCIP_OKAY;
19002 }
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:3299
#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:17715
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:3808
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:18525
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:17923
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:3357
SCIP_RETCODE SCIPcleanupConssLinear(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible)
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17465
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:2851
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17703
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1698
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:17979
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:17444
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:2063
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define NLOCKTYPES
Definition: type_var.h:90
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:3593
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17760
#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:17613
#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:17667
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:3096
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:17475
#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:17749
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:17315
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:2180
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:17739
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17526
#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:3818
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17933
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:96
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:2778
#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:3401
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:3482
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:17679
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:17264
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:17727
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17551
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:17414
#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:17393
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:5040
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:11954
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:17771
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:18515
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:17655
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:17328
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:2228
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:17691
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:2141
#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:12786
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:2045
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:2000
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:3704
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:5747
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:1676
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:3050
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:1955
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:116
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17383
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:1724
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:2209
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:18035
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17603
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2164
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:17429
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:69
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:17989
#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:17406
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:3236
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:17455
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:17485
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:391
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip_prob.c:1276
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:17593
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17419
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